From 28a3d8464ac52ac924488a94b43e3ba082f1d295 Mon Sep 17 00:00:00 2001 From: Ryley Kimmel Date: Wed, 25 Feb 2015 23:58:49 -0500 Subject: [PATCH 01/59] Remove redundant note information and binary note information updater, ItemDefinition already manages this. --- data/note-317.dat | Bin 10565 -> 0 bytes data/note-377.dat | Bin 12362 -> 0 bytes src/org/apollo/tools/NoteUpdater.java | 61 -------------------------- 3 files changed, 61 deletions(-) delete mode 100644 data/note-317.dat delete mode 100644 data/note-377.dat delete mode 100644 src/org/apollo/tools/NoteUpdater.java diff --git a/data/note-317.dat b/data/note-317.dat deleted file mode 100644 index 8438dbb2980b396fa9929b0a7849acee170d54d6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10565 zcmd_vd6-k>y$A4lXEG<5Nitc6NoHJ8Q7J`KYAsUteXm;gmAX=DDMj2j+z}BGcSXge z6nESe6)8nasil-sL`9^ylu|@Rs)(rfb2354Vr#wkpL?I1=lSHE^PVLqzwi6L$z<9t zuc|6S-uU@*s996%+SMc1|Gd3M>!y51OQ`uCTkw6hVjH$&2X2C9jzvzX1x%waC`n9m!$ z#R3+xh{e3i5|;7-%UI3|KCKC%hFTItq-Z2VlbsFshlU5f96$)`bZiKrhhsOPC!4W3 zy&Mw4mTb+oY|oDD%&zRtp6ty&m818!b|43HD2H<-eK?w9Ii9}s<3##1fPoC+6i(v| z&f**fb3PYxF+&*2ForXNkzCEST+fY+;+8MJ)q6DES7{32Ve60bI8X8v&&2O~B9oZR z^Ix1F!XGvKi9hoqFYyYm@*02Pb>8H!{Eff!Ht+Br@AD5nehz z!Axc`o0plxT;?&KH+YK$EMyUjd6y+DIh4aWl0F>G zu^dld`f(!t8NfgWaSEq#24`^&gN>I^e<2q$grRYRd9dC*SZ^MzHxJgE2kXs)^*3-6 zH*+huaRVV|oYx!Y^~QPqZ`ybK>*r9vz+nqn z#A4oM2}}R^q!3B8`UsKH8x>Y=c3g%?R#8{Ft!xfa{JqirMO(yA@`>aVZHs&&`9$)G zc11psd?NWo@`>aV$tRLeB%eq=k$fWgM17D?B%eq=QD5W}$tRLeG@$+ULv*SQpHh)e zsmP~P?GKpjo$t03VB$Mbt%)yaV zB6DzL4vx&hxlD*ASe?iuCcAEkrZANkn8tKwFq2u#=4IwEmwC+R4c=k_3t7ZsBo|38 zTFM73V>v7Mv?e6u7ft%q``3?4F@SUFk-5dVJ-HAt}G4{F1w}JA1M>@=MAu zDZixrlJZN+FDbvI{E~f;Us8Ta`6c_(j}z(700uIMQ#g$?IE!-_%=ui%#SCF6!x+v8 zM#lFXlEzok_l%Gn#Vw5HcJ5>hW4W7qxu0=7#3MY$6YFqe7E=MCOsL3}~q8Iy1G4)5_k|KLMD;$uGHvzm|!)KO282GV3P zGE+WRQ$ANyEtF|vb=G8U)?q!?XG6Zlx7mn|*_7|_UB1T_e4nk@hV9sao!Eul*n_?J z0sHbp4&WdT;V_QiD1O8-aWbhB_%T1>r~Hhcb5bR^l+05yPsuzb^VHzVNfJ*GdtYDWy~XEz$VYt4Cwx{D8UuCIlca$(m0w*#qqG{O)hMk-X*Ei#QCf}CYV3@( z8l}}Jtww1zN~=*?jnZnAR-?2UrPU~{Mrk!lt8q)VW?QyrM|Ngcc4traW*_!re-7ke z4&`u;qz^}PEXUKAew;{u1~8C8Ur~(z3r!*2U25r#zjUu5y_Gh7J-wawklv}XH>CHd zY?;^6=C!nWEp1*)o7d9jwe(>e!BPB(V>k{oTiVQ)HnXM8Y-uxF+RTar~ zIk)4zg!Hh=i;l3vXIMyIQ@xj)tlx}LkiMEse2^X-u79x@w+OplP+IAk^nnN2J0#zLmc$`@&0hRoI>qyJ|%@7NwP zJ80U8UD%C1*lXn>A)~iv%vT|E*vht*m+Mzq37N|G#*mRwMn)MKWn`3*QRZCE;{q;< z4-c84#93Kf8819S<_08{xjEh#&F$RD7{+op_i{huc!)=Mj3*e+)9qKQUNZi)`R0$1 zk%9RpWMz<*K~@G?8DwRUl|fbpSs7$yknKc?R#wAolwFI?NFdvV4d_ZYy3>PA=!rD4 zo70Qln2oYqvn|`lHzAj-T(WY>$|buO##Pq1${JT$<0^YlL(^fQ z>F|)f(W#>xazx19YV|9})>mHne`8~4I;whGq3MMG!3~C{JH*zc*EZ?3O?qw9y)GA; z^w}nTwn?9D(r26W*(QCq>1ie~kx5MEd8ROx7nsI$W-yak%;sh0u zoVg`;F6Ne;xg~cImvAYUaXI>L?nTkcTV# zRz8JX{AZ|U`Q+l+CFG=&lTJ=LIqBr2lbf~j_zugETi9VMK64q%S%DcRuPtxJ$(wQV z5oVmc87FVX$;&D)tGul8vdYUUFRQ$)@@rtm$#=$#lmDkVzw)Xf-^-rf@k?yQHX1`- zYI&*UrIwdkKK{)9+DFI_aOlAJ{F6Hz9P*cS*!l*mA^(I+jjx;$@)NBa19@X0uf};} zAU`|ge`oP~{=gsk6MyE#_%@7zyfKiU%RJ`u25+%|g)Cw*@3MrYe1Ht{GRVsyF9W~M zgn|qTGAPKPAcKMo3Nk3jpdf>S3<@$R$eH(Ro`8id03?8wgS+OdwIU<4J6pu!>5=1?$p3dT;s*eMu01!JdR>=cZhg0WLD zb_&K$!PqGnI|XB>VC)o(or1AbFm?(Te10{freM?*jGBT`Q!r`@?cbp~+(#&kiMK-G zp7`m0#_>?R@o4-c&4M&T;TfLgSNxji;>Lgbi5v=VIwby{RFGL=QRQVMR*+bs^4nS{ zCaSj*ilMsp`63i0Q;fe8{YQ^b+^YS!P~36l38Cm)PblugeknIKSJ^M z9nT3xW1=`GzTemQ3$Iu9hvMI?|DCsahxd5@^K(P-llJ49>#ED@f7Y6F)$Nw*(tjL0 zLi0M+<%ZSeM%88Y*UM(VUV4P)c*cpB)xQs#+vl3lyl=I=`VFS}i0bw+)#Z3OKC`-gUUhj%eDTXe^YGAoMWw0QZpLpm<2T<_-M-EG9sGh{au@e-9}n;#5A!IG z^CVB9H#a}~#f7bf<_8c6$5s!@gJvEuki~)KO282GV57QJ|R?%CxaMYqB=$upaBP zA>ZQLY{bTF%6IrK-(w5D&sJ>1cI?1T?80vB!Cw4;efc2=a1e)Z7)NjvKjIjUmiGSJ-W*ykk5@vA`Jlyo&|*Glxt<#t#Vw5HcJ5>hV=HIeYt3BTGOqnfUw#fP z&)N0&(6T7Bd{wo-eDr^RE0k2bq}nCbE~$1&wM(j9QtgszmsGo?+9lO4sdh=VOR8N` z?UHJjRJ)|wCDksec1g8Ms$Ej;l4_S!yQJDB)h?-aNwrI=T~h6mYL}IvbOL6LP&$$R z3}7IGIEB+VgR?k?!JN;9T+9&6&?Pf;$qZdGLzg5{l1ND+C5eB0tdr5oMpf%_=; zj9=ut@l!8)vn9UqgtF|*vM$T%d#)azAXE)?8~w*%f2l8vh2&UFU!6x`?BoI zarVa{`|^+Z2|wj${G5|GnNvBPGdY`cIgbmth)cMX%eb5?xRR^5hU?-RzL8Pf!f0;i zPR0pwZ8ri91&V~WM_6|clKm&_F+Hv=RgkTP!8uv z`fxPIay)(M$BFc300SAsDV)X`oW(f|=6o*XVumo3VGL&kBe|Muxt<#t#Vw4kzQ52q z*4EwJ%l&a{XnmMRd7LMCDsG&>L?$tr=b6G(USJy2nZZnEF`Ji}!(8SupEr1m1uVoj z+R*wA@9{qW;6py*V?N=tn$Q-gqn;!Uq{)(_Kr=0rX=8QPWNp@AJ=UlFn^~m}p{=Ke u&8ju&un28NUYn8EX5_W))nU(nuo~Jf32j3{+ohpxXlT1Ev<>Tc(tiQTS~fTU diff --git a/data/note-377.dat b/data/note-377.dat deleted file mode 100644 index 488fec5b0486c42641ba86a1972b14927514054f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12362 zcmeI%2XvHWx(D#QDKnE~CYhO#NhX;DP;7{Zb?svBuDTXf?5^v&F3ZKIG95?lz#MQ0EcrVM{_L4b0Pydh0{2Lvlzr+hA@<2T*$>-%5X+7l2KgE zwOr3=ZsHbhV+>=ti+dQ)1ny@dlX#d%d7Q~S$cVkD>{NsXPAw}r~vI|dL!*M&EP(9^NKSe4aTleHWY z!g_2#Z#HIAHfKw=W?QyrhvLyYTiTUA>_K1lW?%N_Kn~(y4&hMx(Vqbv&XF9=u^i8d z4CE9};|$JX5Q7=QP=;|K7jr4Y8NtYoAN6LNZY^#K;ZDnUGmd+?j|ZYpJ&A{Tl*fNO zKZJkS@K6553%tZDyvl35&YQf=yS&Hye85M1%%^_U`M?DSXX~rxq?MzpeW*L_I@uJ(7Lg`vIuY*KOC0g1WiIz&VRHCI4E!{dgIF$aL z9g9o5L>m@=gi^_s_KS9e(!)4{qd11+IDwNmnNvBPGdY`cIG6J{p9{E%OSo+D_xd$k zLg|ae!$awe#ZC*QW>V=V?fbv7Jdbbrz9f|SAZ4YCo%8EAgfg`(Q_C{5qs;6mGds$5 zU?0r)k)VoXw8Q8wH@eG> z?sB8M+~_Vhy33oRovn0XDY~&N%hR16^rRQ7vN~(B7VEGc8_*kLz1&zYmruET%H>lo zpK|$>%copEIG95)3(EV^p8*`sksQsj9M6di=Iqq&J&xQ#K4^Q9_4W+^CV9* zh3A;c^GxGKUS>Kon8_Qw#XHPmHgoupxqQNBe8E@D<6FKj2^A%jQcjEnRV1k)O_omN zXrze(t#n~2y0I+F)14mlq!+8QI%~2P>#!ah(3_3fl+D?at=X3C*@2zdnO*6_9`t2z z_GNz#cP#h_?|E?A)pR_KBix?qJaSfLA6 zT*l>G!IfOaHC)FH+=%;F#jV`V9mSV7*DJ)2~kWWlLvEIlh zCZCvmVp}4gn0#XLiODA>pO}1N@`=eOCZCvmV)BXYi+p18iODB+F!G7XCsw>mwY}$2 zR^6du?ocszsF*uc?BwG06fbFz)xiv5D8sn$$KBG1Nh2nWm^5P2h)E+RjhHlI(uheT zb_aTIOdc`4H>UT-^xoQJh)uLOiHCW#_@0w3J;~Ed;W?)AJkxlQmzmBCX7UDa@eZ?? z%^YMFlUYn=vCsH|ub9WTd|wjc(VNEI?SA?Z;$0lF6y1`q7^O9L|v(&9NNMi45cv zPU8&DVi1EF!cc}q*Bs(zR^0cC5Ff!vMsYRQay_HDiCeghF^uId?qPg%vLxf~qVWf# zm4|th$C=ENJk1oIV=B)x4N1l&8K2G!X7UDa@eZ@17xY~*{sABHF`x1|U-C8I@Et#t zghZf>3gT2!O$u`|;f|VcM@`hzK%Qn==uB6ZW*L@a1y*DwR%R7eV-0@C+N{g^Y{*7z z!e(s2R&2v|{GJ{81G}&ryR#>Iu@C!kK$J}4PyCs`@K^rEe{fhaxP;6TGEc}nA@jt* z;z<%uNIW6&gv1jPPe?o=@x(ALWRt4SC@H0<_Vc6WS)?DLgopXCuE+Gc|zuinaDgL^MuS3 zvzW~sK4dPR@EKq574!I(@BJ#LSe2!e6C*(tNoq)wr4uZIGIy9oijO`b2yjtIG+o+ zh)cMP%ejIpxr%GJjvKg6il~Syn%#+Bma!PdB zq4J;nix+r_S9q1zihJK&?6XDZe96~*!*~2p5~>1aR1l|f?Z4b|)0W~^6l zv|xLv-o|pM*43(YwQ60hT34&q)v9&1>OI+ueb|o!_#^sSwZ2xZuT|@7)%seszE*u0 zM{pF!a2zLa(t>v^zTM#B&!Kj>gN5pgihD!#<(99&9H_o(;WOqhhw53OdYrxYavu-y zAP?~fkMRV5=P91yS^j}>Uv1o1zrahp!mGT->%7U^yc=E8Z07J$sGd9j-GAvhBv%Z{ z9wE6>NcIfLl|!;uNUq|fkTlkl-8!Bgk{g7i@ts_A;q4*0iA|fa1zWKV+s!{DB#q{z zeiV{>&fnJd9Fm6=7ecas^c<2>NJ=3og`^acQb?Y}$(+jRZHEoA7^UIq{OHLeBrii2 z$t$9jQC!WnT+isXqkiL`A^Ckt&^bb?lyYJus3J)XY4nwpzLL^cQu<0tUrFgJDSai? z1+`9fV_Ec-RCjuyucUgRucXvHrLUy)m6X1c(pOUYN~$*-M;9T1lmt=|NJ${I9p*^N z97&lYDRU&XTd@QowU_06Fh5cU@JGy#l=+b|KT_sL%KS)~A1U)AC7G0DQpYT@gdufa zNvPR5)a(*!b`3SVg_=I0X7^CDN2u8|)btIh;Z7alkiA0cN{dUJCrfr%GIh|?X<;Dv2}Kbt)ccS+vf2tdO_L+r1gTdUXYHV z7o_!qv|f-_$+SwQRWhxTX_ZW?WLhQD1@wY+7xaSkB7L{`t|7gaJ?lhou|82%Lt5ue zoA+t+K5gEoqdVg-K0>;`LkC3XAFDN!(Qz|6Zbrw==(rgjH{)KI zaWBlc7iQcGGwy|%Q`=u9WX`d6F8Xigd@i8vo5@0N6f)OGYaw%U^y4Jjg>l!ei0KXpa2kBV^uoNc8O^Bdg3D2ZoHKGLp&^|56pQemuB~T>y3N|x+xkkV+p&GU{d+{+UhV4#v_Jp3{rPY0&u#rB)E(EpescTsnbDh^ z8|sFHy7P*g+P7a~vu|>Bm$$E9W%(Me;|6ZzW^Uzn?%+=DW*ql&A4YQBgFn9T|1YU` zr|5U-&}k~qFDOXpr1y53N%6l(q0_q-jk-=oU8fHg9QNZvs1GHfzKjauR8mcfS~Ap8 zPXl?HX`wS+S(;^7julvul~|coSdBIK9c!~L>$4#nu?d^81zWKV+wpsLJ$%5X+7l2KgEwOr5W;u*JC z(sS#_w7t@zKSTZdp?*%NUsA0XJ@(&S4>`5YsdY}Rb84Ma>zrEW)HO&Z%`yt#fLfQ|p{s=hQl<)(wh~ z`xE*@$Q?>Q`ZIvTIg+C}mg6~*ft#W}q=rx)k+;+#Bk^2o^}Cy$&wa`MQ@ zBPWlXJaY2L$s;$Kn}{w(BDpb){dqpdulyYJus3J)XX|i-8MLZC$6Jm)#y#uh<>caI;@B9GoeBD4YF^LeS_>9WZxkB2H7{rzCrd4vTu-mgX|k* z-yr)2**D0(LG}$%_U2iG>>K{fU-&D3<3BizBRGmar~IfrvOkMp^J zi?}4Z;Ngs5B%`>RYq_3iE_Qr`h6%Rc&qOA5-1*CEp|Nvl>=GKgh6edH$ge?u4fFUG z`8B$xM)@_$uTg%D@@te|qx>4>*C@Y6`8CR~QGSi`Yiy!G>n~q{BSPb*Y|fT!&9-dM z4(!Cv>`EW@pf7u~FZ**K2XQcma47xg&j1eRNRH-Mj^{)Matfz$24^vd!3<$2!?=)( zxs>6IU?ij3KVN7ZZS5v*;kIaNXuOlV8OOcc7j2x#Bp&8b9%nL7@-$O;j;TD)G+yLo zrZa!V{&-s$C`G)WKp(Nx3WmFKSl4?@alA(@z8pzX33!Ul8 z(kw&Ucd+(4Ea55S&APlJEsMDn*WhOykmJ&b1p_al}3B&3p;N?s~?spO@Smr7nLd8y>3l9x(eDtW2o zrIMFQUMl&SNF^_oyj1d1$#?usdr8+Gnl@?Q9GcpGhX_qgC84Q6D_vNMZY&#psHX1p zpeMc1`xbqKrs6l=(6qJv+p;}7uoFA8EA9VV2~E0O(|+wQ5t{V3CjG7HuZzBDhxO33 z$Zy%9>5Ay$Msa0_BmY|~p~<*zihdvK@CZ#ta+8tVY$P`u$<0P`vyt3vBsUw$&8ZH@ zFL5O__gZLsXkO208_=7L*_6%c@H_BAXZ)JQ&}`s_X8pcdzi-y>oAvwVOSp{7xq>UX zifg!z8@Q31xs}_w1D&N=XK5a{$TfuKCv5#YPw`A~Z)pCf<$v)4FYyYm@*1zx_FG!V zmkNcCLi5+rHR~JAs@<&G1=TL7c0siZs$Ed+f@&A^je@>W&^HSDMnT^w=o@1F3I!Davu-yAP?~fk0FzSObRk7Jj1j61GyCB zQjkkQE`?Wk6}c4TQh1ZMc`p=Zhr;_EK4vI-OUojE z^9(IgXj!S_EB)8jLd*U?ePC!g!RwyH$(+jRoXOcl9VE1z$N60F(=YRrdqRuawy15( zQ^nVMb_qv@7Ikb<$Ch__kN5e2kNB8R`8>Lmub5YSi4c8p39V&R5GVSZL}*P>ONKg( z^j0Ii)ktqO(py_F(p!!6)}>j7 itemToNote = new HashMap<>(); - - for (int id = 0; id < defs.length; id++) { - ItemDefinition def = ItemDefinition.lookup(id); - if (def.isNote()) { - itemToNote.put(def.getNoteInfoId(), def.getId()); - } - } - - for (int id = 0; id < defs.length; id++) { - if (itemToNote.containsKey(id)) { - os.writeBoolean(true); // notable - os.writeShort(itemToNote.get(id)); - } else { - os.writeBoolean(false); // not notable - } - } - } - } - -} \ No newline at end of file From e26ed8c8a121f5516f21fdd69d8f199727042b93 Mon Sep 17 00:00:00 2001 From: Ryley Kimmel Date: Thu, 26 Feb 2015 00:03:17 -0500 Subject: [PATCH 02/59] Login/Logout listener formatting. --- src/org/apollo/game/login/LoginDispatcher.java | 6 ++---- src/org/apollo/game/login/LoginListener.java | 2 +- src/org/apollo/game/login/LogoutDispatcher.java | 6 ++---- src/org/apollo/game/login/LogoutListener.java | 2 +- 4 files changed, 6 insertions(+), 10 deletions(-) diff --git a/src/org/apollo/game/login/LoginDispatcher.java b/src/org/apollo/game/login/LoginDispatcher.java index 878fd9c8..98968c27 100644 --- a/src/org/apollo/game/login/LoginDispatcher.java +++ b/src/org/apollo/game/login/LoginDispatcher.java @@ -15,7 +15,7 @@ public final class LoginDispatcher { /** * A {@link List} of login listeners. */ - private List listeners = new ArrayList<>(); + private final List listeners = new ArrayList<>(); /** * Dispatches a player to the appropriate login listener. @@ -23,9 +23,7 @@ public final class LoginDispatcher { * @param player The player. */ public void dispatch(Player player) { - for (LoginListener listener : listeners) { - listener.execute(player); - } + listeners.forEach(listener -> listener.execute(player)); } /** diff --git a/src/org/apollo/game/login/LoginListener.java b/src/org/apollo/game/login/LoginListener.java index 5fcc2ea4..8530178d 100644 --- a/src/org/apollo/game/login/LoginListener.java +++ b/src/org/apollo/game/login/LoginListener.java @@ -15,6 +15,6 @@ public interface LoginListener { * * @param player The player. */ - public abstract void execute(Player player); + public void execute(Player player); } \ No newline at end of file diff --git a/src/org/apollo/game/login/LogoutDispatcher.java b/src/org/apollo/game/login/LogoutDispatcher.java index c7a5e3f8..cc3895eb 100644 --- a/src/org/apollo/game/login/LogoutDispatcher.java +++ b/src/org/apollo/game/login/LogoutDispatcher.java @@ -15,7 +15,7 @@ public final class LogoutDispatcher { /** * A {@link List} of logout listeners. */ - private List listeners = new ArrayList<>(); + private final List listeners = new ArrayList<>(); /** * Dispatches a player to the appropriate logout listener. @@ -23,9 +23,7 @@ public final class LogoutDispatcher { * @param player The player. */ public void dispatch(Player player) { - for (LogoutListener listen : listeners) { - listen.execute(player); - } + listeners.forEach(listener -> listener.execute(player)); } /** diff --git a/src/org/apollo/game/login/LogoutListener.java b/src/org/apollo/game/login/LogoutListener.java index 8a67f5ee..65aa0dfb 100644 --- a/src/org/apollo/game/login/LogoutListener.java +++ b/src/org/apollo/game/login/LogoutListener.java @@ -15,6 +15,6 @@ public interface LogoutListener { * * @param player The player. */ - public abstract void execute(Player player); + public void execute(Player player); } \ No newline at end of file From e2d150b6ca8e8d642d2a185c89b3eefef94da27a Mon Sep 17 00:00:00 2001 From: Ryley Kimmel Date: Thu, 26 Feb 2015 01:01:50 -0500 Subject: [PATCH 03/59] Fix an issue where the mob interaction index was set incorrectly for players. --- src/org/apollo/game/model/entity/Mob.java | 11 ++++++++++- src/org/apollo/game/model/entity/Player.java | 5 +++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/org/apollo/game/model/entity/Mob.java b/src/org/apollo/game/model/entity/Mob.java index 9240dc8e..8bdf5f6f 100644 --- a/src/org/apollo/game/model/entity/Mob.java +++ b/src/org/apollo/game/model/entity/Mob.java @@ -402,6 +402,15 @@ public abstract class Mob extends Entity { this.index = index; } } + + /** + * Returns this mobs interacting index. + * + * @return The interaction index of this mob. + */ + public int getInteractionIndex() { + return index; + } /** * Updates this mob's interacting mob. @@ -410,7 +419,7 @@ public abstract class Mob extends Entity { */ public final void setInteractingMob(Mob mob) { interactingMob = mob; - blockSet.add(SynchronizationBlock.createInteractingMobBlock(mob.index)); + blockSet.add(SynchronizationBlock.createInteractingMobBlock(mob.getInteractionIndex())); } /** diff --git a/src/org/apollo/game/model/entity/Player.java b/src/org/apollo/game/model/entity/Player.java index 2367991e..c2499eb0 100644 --- a/src/org/apollo/game/model/entity/Player.java +++ b/src/org/apollo/game/model/entity/Player.java @@ -355,6 +355,11 @@ public final class Player extends Mob { return EntityType.PLAYER; } + @Override + public int getInteractionIndex() { + return getIndex() | 0x8000; + } + /** * Gets this player's friend chat {@link PrivacyState}. * From 540319c4967dcbff6f1a58a2881a74a19f939992 Mon Sep 17 00:00:00 2001 From: Major- Date: Thu, 26 Feb 2015 18:40:20 +0000 Subject: [PATCH 04/59] Add FlashTabInterfaceMessage. --- .../impl/FlashTabInterfaceMessage.java | 35 +++++++++++++++++++ .../r317/FlashTabInterfaceMessageEncoder.java | 24 +++++++++++++ .../apollo/net/release/r317/Release317.java | 2 ++ .../r377/FlashTabInterfaceMessageEncoder.java | 23 ++++++++++++ .../apollo/net/release/r377/Release377.java | 3 ++ 5 files changed, 87 insertions(+) create mode 100644 src/org/apollo/game/message/impl/FlashTabInterfaceMessage.java create mode 100644 src/org/apollo/net/release/r317/FlashTabInterfaceMessageEncoder.java create mode 100644 src/org/apollo/net/release/r377/FlashTabInterfaceMessageEncoder.java diff --git a/src/org/apollo/game/message/impl/FlashTabInterfaceMessage.java b/src/org/apollo/game/message/impl/FlashTabInterfaceMessage.java new file mode 100644 index 00000000..e6fb19d7 --- /dev/null +++ b/src/org/apollo/game/message/impl/FlashTabInterfaceMessage.java @@ -0,0 +1,35 @@ +package org.apollo.game.message.impl; + +import org.apollo.game.message.Message; + +/** + * A {@link Message} sent to the client to + * + * @author Major + */ +public final class FlashTabInterfaceMessage extends Message { + + /** + * The id of the tab to flash. + */ + private final int tab; + + /** + * Creates the FlashTabInterfaceMessage. + * + * @param tab The id of the tab to flash. + */ + public FlashTabInterfaceMessage(int tab) { + this.tab = tab; + } + + /** + * Gets the id of the tab to flash. + * + * @return The id. + */ + public int getTab() { + return tab; + } + +} \ No newline at end of file diff --git a/src/org/apollo/net/release/r317/FlashTabInterfaceMessageEncoder.java b/src/org/apollo/net/release/r317/FlashTabInterfaceMessageEncoder.java new file mode 100644 index 00000000..1bc1d698 --- /dev/null +++ b/src/org/apollo/net/release/r317/FlashTabInterfaceMessageEncoder.java @@ -0,0 +1,24 @@ +package org.apollo.net.release.r317; + +import org.apollo.game.message.impl.FlashTabInterfaceMessage; +import org.apollo.net.codec.game.DataTransformation; +import org.apollo.net.codec.game.DataType; +import org.apollo.net.codec.game.GamePacket; +import org.apollo.net.codec.game.GamePacketBuilder; +import org.apollo.net.release.MessageEncoder; + +/** + * A {@link MessageEncoder} for the {@link FlashTabInterfaceMessage}. + * + * @author Major + */ +public final class FlashTabInterfaceMessageEncoder extends MessageEncoder { + + @Override + public GamePacket encode(FlashTabInterfaceMessage message) { + GamePacketBuilder builder = new GamePacketBuilder(24); + builder.put(DataType.BYTE, DataTransformation.SUBTRACT, message.getTab()); + return builder.toGamePacket(); + } + +} \ No newline at end of file diff --git a/src/org/apollo/net/release/r317/Release317.java b/src/org/apollo/net/release/r317/Release317.java index e1abf5d8..e011e1d8 100644 --- a/src/org/apollo/net/release/r317/Release317.java +++ b/src/org/apollo/net/release/r317/Release317.java @@ -7,6 +7,7 @@ import org.apollo.game.message.impl.ConfigMessage; import org.apollo.game.message.impl.DisplayCrossbonesMessage; import org.apollo.game.message.impl.DisplayTabInterfaceMessage; import org.apollo.game.message.impl.EnterAmountMessage; +import org.apollo.game.message.impl.FlashTabInterfaceMessage; import org.apollo.game.message.impl.ForwardPrivateChatMessage; import org.apollo.game.message.impl.FriendServerStatusMessage; import org.apollo.game.message.impl.HintIconMessage; @@ -207,5 +208,6 @@ public final class Release317 extends Release { register(IgnoreListMessage.class, new IgnoreListMessageEncoder()); register(SendFriendMessage.class, new SendFriendMessageEncoder()); register(HintIconMessage.class, new HintIconMessageEncoder()); + register(FlashTabInterfaceMessage.class, new FlashTabInterfaceMessageEncoder()); } } \ No newline at end of file diff --git a/src/org/apollo/net/release/r377/FlashTabInterfaceMessageEncoder.java b/src/org/apollo/net/release/r377/FlashTabInterfaceMessageEncoder.java new file mode 100644 index 00000000..b64eeaff --- /dev/null +++ b/src/org/apollo/net/release/r377/FlashTabInterfaceMessageEncoder.java @@ -0,0 +1,23 @@ +package org.apollo.net.release.r377; + +import org.apollo.game.message.impl.FlashTabInterfaceMessage; +import org.apollo.net.codec.game.DataType; +import org.apollo.net.codec.game.GamePacket; +import org.apollo.net.codec.game.GamePacketBuilder; +import org.apollo.net.release.MessageEncoder; + +/** + * A {@link MessageEncoder} for the {@link FlashTabInterfaceMessage}. + * + * @author Major + */ +public final class FlashTabInterfaceMessageEncoder extends MessageEncoder { + + @Override + public GamePacket encode(FlashTabInterfaceMessage message) { + GamePacketBuilder builder = new GamePacketBuilder(283); + builder.put(DataType.BYTE, message.getTab()); + return builder.toGamePacket(); + } + +} \ No newline at end of file diff --git a/src/org/apollo/net/release/r377/Release377.java b/src/org/apollo/net/release/r377/Release377.java index 72bf88f7..d943f6bd 100644 --- a/src/org/apollo/net/release/r377/Release377.java +++ b/src/org/apollo/net/release/r377/Release377.java @@ -7,6 +7,7 @@ import org.apollo.game.message.impl.ConfigMessage; import org.apollo.game.message.impl.DisplayCrossbonesMessage; import org.apollo.game.message.impl.DisplayTabInterfaceMessage; import org.apollo.game.message.impl.EnterAmountMessage; +import org.apollo.game.message.impl.FlashTabInterfaceMessage; import org.apollo.game.message.impl.ForwardPrivateChatMessage; import org.apollo.game.message.impl.FriendServerStatusMessage; import org.apollo.game.message.impl.HintIconMessage; @@ -41,6 +42,7 @@ import org.apollo.game.message.impl.UpdateTileItemMessage; import org.apollo.game.message.impl.UpdateWeightMessage; import org.apollo.net.meta.PacketMetaDataGroup; import org.apollo.net.release.Release; +import org.apollo.net.release.r317.FlashTabInterfaceMessageEncoder; /** * A {@link Release} implementation for the 377 protocol. @@ -203,6 +205,7 @@ public final class Release377 extends Release { register(IgnoreListMessage.class, new IgnoreListMessageEncoder()); register(SendFriendMessage.class, new SendFriendMessageEncoder()); register(HintIconMessage.class, new HintIconMessageEncoder()); + register(FlashTabInterfaceMessage.class, new FlashTabInterfaceMessageEncoder()); } } \ No newline at end of file From e6301dd6b6f6de6fef913c5a63009a557ec6b3b9 Mon Sep 17 00:00:00 2001 From: Ryley Kimmel Date: Thu, 26 Feb 2015 13:50:28 -0500 Subject: [PATCH 05/59] Remove duplicate openBank method. --- .../apollo/game/model/inter/bank/BankUtils.java | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/src/org/apollo/game/model/inter/bank/BankUtils.java b/src/org/apollo/game/model/inter/bank/BankUtils.java index faa81818..0bb3e32f 100644 --- a/src/org/apollo/game/model/inter/bank/BankUtils.java +++ b/src/org/apollo/game/model/inter/bank/BankUtils.java @@ -65,18 +65,8 @@ public final class BankUtils { * @param player The player. */ public static void openBank(Player player) { - InventoryListener invListener = new SynchronizationInventoryListener(player, BankConstants.SIDEBAR_INVENTORY_ID); - InventoryListener bankListener = new SynchronizationInventoryListener(player, BankConstants.BANK_INVENTORY_ID); - - player.getInventory().addListener(invListener); - player.getBank().addListener(bankListener); - - player.getInventory().forceRefresh(); - player.getBank().forceRefresh(); - - InterfaceListener interListener = new BankInterfaceListener(player, invListener, bankListener); - - player.getInterfaceSet().openWindowWithSidebar(interListener, BankConstants.BANK_WINDOW_ID, BankConstants.SIDEBAR_ID); + // Required for access within plugin Actions. + player.openBank(); } /** From 52eb84930df020845c2417cc44d35d5a12a6b146 Mon Sep 17 00:00:00 2001 From: Ryley Kimmel Date: Thu, 26 Feb 2015 13:52:21 -0500 Subject: [PATCH 06/59] Remove unused imports. --- src/org/apollo/game/model/inter/bank/BankUtils.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/org/apollo/game/model/inter/bank/BankUtils.java b/src/org/apollo/game/model/inter/bank/BankUtils.java index 0bb3e32f..75cffec8 100644 --- a/src/org/apollo/game/model/inter/bank/BankUtils.java +++ b/src/org/apollo/game/model/inter/bank/BankUtils.java @@ -3,10 +3,7 @@ package org.apollo.game.model.inter.bank; import org.apollo.game.model.Item; import org.apollo.game.model.def.ItemDefinition; import org.apollo.game.model.entity.Player; -import org.apollo.game.model.inter.InterfaceListener; import org.apollo.game.model.inv.Inventory; -import org.apollo.game.model.inv.InventoryListener; -import org.apollo.game.model.inv.SynchronizationInventoryListener; /** * Contains bank-related utility methods. From 00627e0f486bd9f8b15ba838b119f14f41dbd5a8 Mon Sep 17 00:00:00 2001 From: Ryley Kimmel Date: Thu, 26 Feb 2015 13:56:01 -0500 Subject: [PATCH 07/59] Use player#openBank() over BankUtils#openBank(Player). --- data/plugins/cmd/bank/bank.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/data/plugins/cmd/bank/bank.rb b/data/plugins/cmd/bank/bank.rb index 6c28fa91..3b210064 100644 --- a/data/plugins/cmd/bank/bank.rb +++ b/data/plugins/cmd/bank/bank.rb @@ -1,8 +1,6 @@ require 'java' -java_import 'org.apollo.game.model.inter.bank.BankUtils' - # Opens the player's bank. on :command, :bank, RIGHTS_ADMIN do |player, command| - BankUtils.open_bank(player) + player.open_bank end \ No newline at end of file From 441bc9eb7783568d01a996f02981386c71ba8230 Mon Sep 17 00:00:00 2001 From: Major- Date: Thu, 26 Feb 2015 21:03:59 +0000 Subject: [PATCH 08/59] Fix IdAssignment issue. --- src/org/apollo/game/GameService.java | 15 ++++++++--- src/org/apollo/net/session/LoginSession.java | 28 +++++++++----------- 2 files changed, 23 insertions(+), 20 deletions(-) diff --git a/src/org/apollo/game/GameService.java b/src/org/apollo/game/GameService.java index 31cc3730..3f647950 100644 --- a/src/org/apollo/game/GameService.java +++ b/src/org/apollo/game/GameService.java @@ -148,14 +148,21 @@ public final class GameService extends Service { } /** - * Registers a player (may block!). + * Registers a {@link Player} (may block!). * - * @param player The player. + * @param player The Player. + * @param session The {@link GameSession} of the Player. + * @param reconnecting The reconnecting flag. * @return A {@link RegistrationStatus}. */ - public RegistrationStatus registerPlayer(Player player) { + public RegistrationStatus registerPlayer(Player player, GameSession session, boolean reconnecting) { synchronized (this) { - return World.getWorld().register(player); + RegistrationStatus status = World.getWorld().register(player); + if (status == RegistrationStatus.OK) { + player.setSession(session, reconnecting); + } + + return status; } } diff --git a/src/org/apollo/net/session/LoginSession.java b/src/org/apollo/net/session/LoginSession.java index 1d0712aa..827249d0 100644 --- a/src/org/apollo/net/session/LoginSession.java +++ b/src/org/apollo/net/session/LoginSession.java @@ -85,37 +85,33 @@ public final class LoginSession extends Session { * @param response The response. */ public void handlePlayerLoaderResponse(LoginRequest request, PlayerLoaderResponse response) { - GameService gameService = serverContext.getService(GameService.class); + GameService service = serverContext.getService(GameService.class); Channel channel = getChannel(); - Optional responsePlayer = response.getPlayer(); + Optional optional = response.getPlayer(); int status = response.getStatus(), rights = 0; boolean flagged = false; - if (responsePlayer.isPresent()) { - Player player = responsePlayer.get(); + if (optional.isPresent()) { + Player player = optional.get(); rights = player.getPrivilegeLevel().toInteger(); GameSession session = new GameSession(channel, serverContext, player); - player.setSession(session, false /* TODO */); + RegistrationStatus registration = service.registerPlayer(player, session, request.isReconnecting()); - RegistrationStatus registrationStatus = gameService.registerPlayer(player); - - if (registrationStatus != RegistrationStatus.OK) { - responsePlayer = Optional.empty(); + if (registration != RegistrationStatus.OK) { + optional = Optional.empty(); rights = 0; - if (registrationStatus == RegistrationStatus.ALREADY_ONLINE) { - status = LoginConstants.STATUS_ACCOUNT_ONLINE; - } else { - status = LoginConstants.STATUS_SERVER_FULL; - } + + status = (registration == RegistrationStatus.ALREADY_ONLINE) ? LoginConstants.STATUS_ACCOUNT_ONLINE + : LoginConstants.STATUS_SERVER_FULL; } } ChannelFuture future = channel.writeAndFlush(new LoginResponse(status, rights, flagged)); destroy(); - if (responsePlayer.isPresent()) { + if (optional.isPresent()) { IsaacRandomPair randomPair = request.getRandomPair(); Release release = serverContext.getRelease(); @@ -129,7 +125,7 @@ public final class LoginSession extends Session { channel.pipeline().remove("loginDecoder"); channel.pipeline().remove("loginEncoder"); - channelContext.attr(NetworkConstants.SESSION_KEY).set(responsePlayer.get().getSession()); + channelContext.attr(NetworkConstants.SESSION_KEY).set(optional.get().getSession()); } else { future.addListener(ChannelFutureListener.CLOSE); } From 5fe5aa394096606f95ceeee5936d254d0b6e1c14 Mon Sep 17 00:00:00 2001 From: Major- Date: Thu, 26 Feb 2015 21:23:37 +0000 Subject: [PATCH 09/59] Add support for simple overlay interfaces. --- ....java => OpenInterfaceOverlayMessage.java} | 24 ++++++------- .../game/message/impl/OpenOverlayMessage.java | 35 +++++++++++++++++++ .../apollo/game/model/inter/InterfaceSet.java | 32 +++++++++++++++-- ...> OpenInterfaceOverlayMessageEncoder.java} | 10 +++--- .../r317/OpenOverlayMessageEncoder.java | 24 +++++++++++++ .../apollo/net/release/r317/Release317.java | 6 ++-- ...> OpenInterfaceOverlayMessageEncoder.java} | 10 +++--- .../r377/OpenOverlayMessageEncoder.java | 25 +++++++++++++ .../apollo/net/release/r377/Release377.java | 7 ++-- 9 files changed, 144 insertions(+), 29 deletions(-) rename src/org/apollo/game/message/impl/{OpenInterfaceSidebarMessage.java => OpenInterfaceOverlayMessage.java} (54%) create mode 100644 src/org/apollo/game/message/impl/OpenOverlayMessage.java rename src/org/apollo/net/release/r317/{OpenInterfaceSidebarMessageEncoder.java => OpenInterfaceOverlayMessageEncoder.java} (58%) create mode 100644 src/org/apollo/net/release/r317/OpenOverlayMessageEncoder.java rename src/org/apollo/net/release/r377/{OpenInterfaceSidebarMessageEncoder.java => OpenInterfaceOverlayMessageEncoder.java} (64%) create mode 100644 src/org/apollo/net/release/r377/OpenOverlayMessageEncoder.java diff --git a/src/org/apollo/game/message/impl/OpenInterfaceSidebarMessage.java b/src/org/apollo/game/message/impl/OpenInterfaceOverlayMessage.java similarity index 54% rename from src/org/apollo/game/message/impl/OpenInterfaceSidebarMessage.java rename to src/org/apollo/game/message/impl/OpenInterfaceOverlayMessage.java index 276047e6..1d34521d 100644 --- a/src/org/apollo/game/message/impl/OpenInterfaceSidebarMessage.java +++ b/src/org/apollo/game/message/impl/OpenInterfaceOverlayMessage.java @@ -3,11 +3,11 @@ package org.apollo.game.message.impl; import org.apollo.game.message.Message; /** - * A {@link Message} sent to the client to open an interface and temporary sidebar overlay. + * A {@link Message} sent to the client to open an interface and temporary overlay. * * @author Graham */ -public final class OpenInterfaceSidebarMessage extends Message { +public final class OpenInterfaceOverlayMessage extends Message { /** * The interface id. @@ -15,19 +15,19 @@ public final class OpenInterfaceSidebarMessage extends Message { private final int interfaceId; /** - * The sidebar id. + * The overlay id. */ - private final int sidebarId; + private final int overlayId; /** - * Creates the open interface sidebar message. + * Creates the open interface overlay message. * * @param interfaceId The interface id. - * @param sidebarId The sidebar id. + * @param overlayId The overlay id. */ - public OpenInterfaceSidebarMessage(int interfaceId, int sidebarId) { + public OpenInterfaceOverlayMessage(int interfaceId, int overlayId) { this.interfaceId = interfaceId; - this.sidebarId = sidebarId; + this.overlayId = overlayId; } /** @@ -40,12 +40,12 @@ public final class OpenInterfaceSidebarMessage extends Message { } /** - * Gets the sidebar id. + * Gets the overlay id. * - * @return The sidebar id. + * @return The overlay id. */ - public int getSidebarId() { - return sidebarId; + public int getOverlayId() { + return overlayId; } } \ No newline at end of file diff --git a/src/org/apollo/game/message/impl/OpenOverlayMessage.java b/src/org/apollo/game/message/impl/OpenOverlayMessage.java new file mode 100644 index 00000000..90ad7dbc --- /dev/null +++ b/src/org/apollo/game/message/impl/OpenOverlayMessage.java @@ -0,0 +1,35 @@ +package org.apollo.game.message.impl; + +import org.apollo.game.message.Message; + +/** + * A {@link Message} sent to the client to open an overlay interface. + * + * @author Major + */ +public final class OpenOverlayMessage extends Message { + + /** + * The overlay id. + */ + private final int overlayId; + + /** + * Creates the open interface overlay message. + * + * @param overlayId The overlay id. + */ + public OpenOverlayMessage(int overlayId) { + this.overlayId = overlayId; + } + + /** + * Gets the overlay id. + * + * @return The overlay id. + */ + public int getOverlayId() { + return overlayId; + } + +} \ No newline at end of file diff --git a/src/org/apollo/game/model/inter/InterfaceSet.java b/src/org/apollo/game/model/inter/InterfaceSet.java index 72835dac..b2178eac 100644 --- a/src/org/apollo/game/model/inter/InterfaceSet.java +++ b/src/org/apollo/game/model/inter/InterfaceSet.java @@ -8,9 +8,11 @@ import org.apollo.game.message.impl.CloseInterfaceMessage; import org.apollo.game.message.impl.EnterAmountMessage; import org.apollo.game.message.impl.OpenDialogueInterfaceMessage; import org.apollo.game.message.impl.OpenInterfaceMessage; -import org.apollo.game.message.impl.OpenInterfaceSidebarMessage; +import org.apollo.game.message.impl.OpenInterfaceOverlayMessage; +import org.apollo.game.message.impl.OpenOverlayMessage; import org.apollo.game.model.entity.Player; import org.apollo.game.model.inter.dialogue.DialogueListener; +import org.apollo.game.model.inv.InventoryListener; /** * Represents the set of interfaces the player has open. @@ -217,7 +219,33 @@ public final class InterfaceSet { interfaces.put(InterfaceType.WINDOW, windowId); interfaces.put(InterfaceType.SIDEBAR, sidebarId); - player.send(new OpenInterfaceSidebarMessage(windowId, sidebarId)); + player.send(new OpenInterfaceOverlayMessage(windowId, sidebarId)); + } + + /** + * Opens an overlay interface. + * + * @param overlay The overlay id. + */ + public void openOverlay(int overlay) { + closeAndNotify(); + interfaces.put(InterfaceType.OVERLAY, overlay); + + player.send(new OpenOverlayMessage(overlay)); + } + + /** + * Opens an overlay interface with the specified {@link InventoryListener}. + * + * @param listener The listener. + * @param overlay The overlay id. + */ + public void openOverlay(InterfaceListener listener, int overlay) { + closeAndNotify(); + this.listener = Optional.ofNullable(listener); + interfaces.put(InterfaceType.OVERLAY, overlay); + + player.send(new OpenOverlayMessage(overlay)); } /** diff --git a/src/org/apollo/net/release/r317/OpenInterfaceSidebarMessageEncoder.java b/src/org/apollo/net/release/r317/OpenInterfaceOverlayMessageEncoder.java similarity index 58% rename from src/org/apollo/net/release/r317/OpenInterfaceSidebarMessageEncoder.java rename to src/org/apollo/net/release/r317/OpenInterfaceOverlayMessageEncoder.java index a13edd65..1a1d18c9 100644 --- a/src/org/apollo/net/release/r317/OpenInterfaceSidebarMessageEncoder.java +++ b/src/org/apollo/net/release/r317/OpenInterfaceOverlayMessageEncoder.java @@ -1,6 +1,6 @@ package org.apollo.net.release.r317; -import org.apollo.game.message.impl.OpenInterfaceSidebarMessage; +import org.apollo.game.message.impl.OpenInterfaceOverlayMessage; import org.apollo.net.codec.game.DataTransformation; import org.apollo.net.codec.game.DataType; import org.apollo.net.codec.game.GamePacket; @@ -8,17 +8,17 @@ import org.apollo.net.codec.game.GamePacketBuilder; import org.apollo.net.release.MessageEncoder; /** - * A {@link MessageEncoder} for the {@link OpenInterfaceSidebarMessage}. + * A {@link MessageEncoder} for the {@link OpenInterfaceOverlayMessage}. * * @author Graham */ -public final class OpenInterfaceSidebarMessageEncoder extends MessageEncoder { +public final class OpenInterfaceOverlayMessageEncoder extends MessageEncoder { @Override - public GamePacket encode(OpenInterfaceSidebarMessage message) { + public GamePacket encode(OpenInterfaceOverlayMessage message) { GamePacketBuilder builder = new GamePacketBuilder(248); builder.put(DataType.SHORT, DataTransformation.ADD, message.getInterfaceId()); - builder.put(DataType.SHORT, message.getSidebarId()); + builder.put(DataType.SHORT, message.getOverlayId()); return builder.toGamePacket(); } diff --git a/src/org/apollo/net/release/r317/OpenOverlayMessageEncoder.java b/src/org/apollo/net/release/r317/OpenOverlayMessageEncoder.java new file mode 100644 index 00000000..f9ff4a8c --- /dev/null +++ b/src/org/apollo/net/release/r317/OpenOverlayMessageEncoder.java @@ -0,0 +1,24 @@ +package org.apollo.net.release.r317; + +import org.apollo.game.message.impl.OpenOverlayMessage; +import org.apollo.net.codec.game.DataOrder; +import org.apollo.net.codec.game.DataType; +import org.apollo.net.codec.game.GamePacket; +import org.apollo.net.codec.game.GamePacketBuilder; +import org.apollo.net.release.MessageEncoder; + +/** + * A {@link MessageEncoder} for the {@link OpenOverlayMessage}. + * + * @author Major + */ +public final class OpenOverlayMessageEncoder extends MessageEncoder { + + @Override + public GamePacket encode(OpenOverlayMessage message) { + GamePacketBuilder builder = new GamePacketBuilder(142); + builder.put(DataType.SHORT, DataOrder.LITTLE, message.getOverlayId()); + return builder.toGamePacket(); + } + +} \ No newline at end of file diff --git a/src/org/apollo/net/release/r317/Release317.java b/src/org/apollo/net/release/r317/Release317.java index e011e1d8..e57d1d9e 100644 --- a/src/org/apollo/net/release/r317/Release317.java +++ b/src/org/apollo/net/release/r317/Release317.java @@ -17,7 +17,8 @@ import org.apollo.game.message.impl.LogoutMessage; import org.apollo.game.message.impl.NpcSynchronizationMessage; import org.apollo.game.message.impl.OpenDialogueInterfaceMessage; import org.apollo.game.message.impl.OpenInterfaceMessage; -import org.apollo.game.message.impl.OpenInterfaceSidebarMessage; +import org.apollo.game.message.impl.OpenInterfaceOverlayMessage; +import org.apollo.game.message.impl.OpenOverlayMessage; import org.apollo.game.message.impl.PlayerSynchronizationMessage; import org.apollo.game.message.impl.PositionMessage; import org.apollo.game.message.impl.PrivacyOptionMessage; @@ -178,7 +179,7 @@ public final class Release317 extends Release { register(UpdateItemsMessage.class, new UpdateItemsMessageEncoder()); register(UpdateSlottedItemsMessage.class, new UpdateSlottedItemsMessageEncoder()); register(UpdateSkillMessage.class, new UpdateSkillMessageEncoder()); - register(OpenInterfaceSidebarMessage.class, new OpenInterfaceSidebarMessageEncoder()); + register(OpenInterfaceOverlayMessage.class, new OpenInterfaceOverlayMessageEncoder()); register(EnterAmountMessage.class, new EnterAmountMessageEncoder()); register(SetWidgetTextMessage.class, new SetWidgetTextMessageEncoder()); register(NpcSynchronizationMessage.class, new NpcSynchronizationMessageEncoder()); @@ -209,5 +210,6 @@ public final class Release317 extends Release { register(SendFriendMessage.class, new SendFriendMessageEncoder()); register(HintIconMessage.class, new HintIconMessageEncoder()); register(FlashTabInterfaceMessage.class, new FlashTabInterfaceMessageEncoder()); + register(OpenOverlayMessage.class, new OpenOverlayMessageEncoder()); } } \ No newline at end of file diff --git a/src/org/apollo/net/release/r377/OpenInterfaceSidebarMessageEncoder.java b/src/org/apollo/net/release/r377/OpenInterfaceOverlayMessageEncoder.java similarity index 64% rename from src/org/apollo/net/release/r377/OpenInterfaceSidebarMessageEncoder.java rename to src/org/apollo/net/release/r377/OpenInterfaceOverlayMessageEncoder.java index 543c509a..2a83cc8c 100644 --- a/src/org/apollo/net/release/r377/OpenInterfaceSidebarMessageEncoder.java +++ b/src/org/apollo/net/release/r377/OpenInterfaceOverlayMessageEncoder.java @@ -1,6 +1,6 @@ package org.apollo.net.release.r377; -import org.apollo.game.message.impl.OpenInterfaceSidebarMessage; +import org.apollo.game.message.impl.OpenInterfaceOverlayMessage; import org.apollo.net.codec.game.DataOrder; import org.apollo.net.codec.game.DataTransformation; import org.apollo.net.codec.game.DataType; @@ -9,17 +9,17 @@ import org.apollo.net.codec.game.GamePacketBuilder; import org.apollo.net.release.MessageEncoder; /** - * A {@link MessageEncoder} for the {@link OpenInterfaceSidebarMessage}. + * A {@link MessageEncoder} for the {@link OpenInterfaceOverlayMessage}. * * @author Graham */ -public final class OpenInterfaceSidebarMessageEncoder extends MessageEncoder { +public final class OpenInterfaceOverlayMessageEncoder extends MessageEncoder { @Override - public GamePacket encode(OpenInterfaceSidebarMessage message) { + public GamePacket encode(OpenInterfaceOverlayMessage message) { GamePacketBuilder builder = new GamePacketBuilder(128); builder.put(DataType.SHORT, DataTransformation.ADD, message.getInterfaceId()); - builder.put(DataType.SHORT, DataOrder.LITTLE, DataTransformation.ADD, message.getSidebarId()); + builder.put(DataType.SHORT, DataOrder.LITTLE, DataTransformation.ADD, message.getOverlayId()); return builder.toGamePacket(); } diff --git a/src/org/apollo/net/release/r377/OpenOverlayMessageEncoder.java b/src/org/apollo/net/release/r377/OpenOverlayMessageEncoder.java new file mode 100644 index 00000000..e3364138 --- /dev/null +++ b/src/org/apollo/net/release/r377/OpenOverlayMessageEncoder.java @@ -0,0 +1,25 @@ +package org.apollo.net.release.r377; + +import org.apollo.game.message.impl.OpenOverlayMessage; +import org.apollo.net.codec.game.DataOrder; +import org.apollo.net.codec.game.DataTransformation; +import org.apollo.net.codec.game.DataType; +import org.apollo.net.codec.game.GamePacket; +import org.apollo.net.codec.game.GamePacketBuilder; +import org.apollo.net.release.MessageEncoder; + +/** + * A {@link MessageEncoder} for the {@link OpenOverlayMessage}. + * + * @author Major + */ +public final class OpenOverlayMessageEncoder extends MessageEncoder { + + @Override + public GamePacket encode(OpenOverlayMessage message) { + GamePacketBuilder builder = new GamePacketBuilder(246); + builder.put(DataType.SHORT, DataOrder.LITTLE, DataTransformation.ADD, message.getOverlayId()); + return builder.toGamePacket(); + } + +} \ No newline at end of file diff --git a/src/org/apollo/net/release/r377/Release377.java b/src/org/apollo/net/release/r377/Release377.java index d943f6bd..9cee1c14 100644 --- a/src/org/apollo/net/release/r377/Release377.java +++ b/src/org/apollo/net/release/r377/Release377.java @@ -17,7 +17,8 @@ import org.apollo.game.message.impl.LogoutMessage; import org.apollo.game.message.impl.NpcSynchronizationMessage; import org.apollo.game.message.impl.OpenDialogueInterfaceMessage; import org.apollo.game.message.impl.OpenInterfaceMessage; -import org.apollo.game.message.impl.OpenInterfaceSidebarMessage; +import org.apollo.game.message.impl.OpenInterfaceOverlayMessage; +import org.apollo.game.message.impl.OpenOverlayMessage; import org.apollo.game.message.impl.PlayerSynchronizationMessage; import org.apollo.game.message.impl.PositionMessage; import org.apollo.game.message.impl.PrivacyOptionMessage; @@ -42,7 +43,6 @@ import org.apollo.game.message.impl.UpdateTileItemMessage; import org.apollo.game.message.impl.UpdateWeightMessage; import org.apollo.net.meta.PacketMetaDataGroup; import org.apollo.net.release.Release; -import org.apollo.net.release.r317.FlashTabInterfaceMessageEncoder; /** * A {@link Release} implementation for the 377 protocol. @@ -175,7 +175,7 @@ public final class Release377 extends Release { register(UpdateItemsMessage.class, new UpdateItemsMessageEncoder()); register(UpdateSlottedItemsMessage.class, new UpdateSlottedItemsMessageEncoder()); register(UpdateSkillMessage.class, new UpdateSkillMessageEncoder()); - register(OpenInterfaceSidebarMessage.class, new OpenInterfaceSidebarMessageEncoder()); + register(OpenInterfaceOverlayMessage.class, new OpenInterfaceOverlayMessageEncoder()); register(EnterAmountMessage.class, new EnterAmountMessageEncoder()); register(SetWidgetTextMessage.class, new SetWidgetTexMessageEncoder()); register(NpcSynchronizationMessage.class, new NpcSynchronizationMessageEncoder()); @@ -206,6 +206,7 @@ public final class Release377 extends Release { register(SendFriendMessage.class, new SendFriendMessageEncoder()); register(HintIconMessage.class, new HintIconMessageEncoder()); register(FlashTabInterfaceMessage.class, new FlashTabInterfaceMessageEncoder()); + register(OpenOverlayMessage.class, new OpenOverlayMessageEncoder()); } } \ No newline at end of file From 369fa6e6617ee3c93c4f3fe652102b14b15e0ace Mon Sep 17 00:00:00 2001 From: Ryley Kimmel Date: Thu, 26 Feb 2015 17:14:10 -0500 Subject: [PATCH 10/59] Remove unnecessary skill dependency from consumable Potions. --- data/plugins/consumables/plugin.xml | 4 +--- data/plugins/consumables/potions.rb | 3 +++ 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/data/plugins/consumables/plugin.xml b/data/plugins/consumables/plugin.xml index 1017d547..8acb8325 100644 --- a/data/plugins/consumables/plugin.xml +++ b/data/plugins/consumables/plugin.xml @@ -6,13 +6,11 @@ Adds support for consumables (e.g. potions, food). Major + Ryley Kimmel - - skill-herblore - \ No newline at end of file diff --git a/data/plugins/consumables/potions.rb b/data/plugins/consumables/potions.rb index ed27a5ce..3ec4c8a0 100644 --- a/data/plugins/consumables/potions.rb +++ b/data/plugins/consumables/potions.rb @@ -2,7 +2,10 @@ require 'java' java_import 'org.apollo.game.model.entity.Skill' +private + DRINK_POTION_SOUND = 334 +EMPTY_VIAL_ID = 229 # A drinkable potion. class Potion < Consumable From 36fe2933b52fe676c174b65a7af3cf36d1d95d09 Mon Sep 17 00:00:00 2001 From: Ryley Kimmel Date: Thu, 26 Feb 2015 17:15:48 -0500 Subject: [PATCH 11/59] Add support for 'slices' of food (pizza, cakes). Fix skill constant that did not exist. Add support for different food delays. --- data/plugins/consumables/food.rb | 92 ++++++++++++++++++++++---------- 1 file changed, 63 insertions(+), 29 deletions(-) diff --git a/data/plugins/consumables/food.rb b/data/plugins/consumables/food.rb index 025b0ea2..cfbe600b 100644 --- a/data/plugins/consumables/food.rb +++ b/data/plugins/consumables/food.rb @@ -4,57 +4,91 @@ java_import 'org.apollo.game.model.Animation' java_import 'org.apollo.game.model.entity.Skill' java_import 'org.apollo.game.model.entity.Player' -EAT_FOOD_SOUND = 317 +private -# Todo support other foods (e.g. pizza) +EAT_FOOD_SOUND = 317 # Represents an edible piece of food, such as bread or fish. class Food < Consumable - def initialize(name, id, restoration) + def initialize(name, id, restoration, replace) super(name, id, EAT_FOOD_SOUND) @restoration = restoration + @replace = replace end # Restore the appropriate amount of hitpoints when consumed. def consume(player) - hitpoints = player.skill_set.skill(HITPOINTS_SKILL_ID) + hitpoints = player.skill_set.skill(Skill::HITPOINTS) new_curr = [ hitpoints.current_level + @restoration, hitpoints.maximum_level ].min - player.skill_set.set_skill(HITPOINTS_SKILL_ID, Skill.new(hitpoints.experience, new_curr, hitpoints.maximum_level)) + player.inventory.add(@replace) unless (@replace == -1) + player.send_message("You eat the #{name}.", true) + player.send_message("It heals some health.", true) if new_curr == hitpoints + + player.skill_set.set_skill(Skill::HITPOINTS, Skill.new(hitpoints.experience, new_curr, hitpoints.maximum_level)) end end # Appends a food item to the list of consumables. -def append_food(hash) +def food(hash) raise 'Hash must contain a name, id, and a restoration value.' unless (hash.has_keys?(:name, :id, :restoration)) - name = hash[:name]; id = hash[:id]; restoration = hash[:restoration] + name = hash[:name]; id = hash[:id]; restoration = hash[:restoration]; replace = hash[:replace] || -1; @delay = hash[:delay] || 3 - append_consumable(Food.new(name, id, restoration)) + append_consumable(Food.new(name, id, restoration, replace)) end -append_food :name => :bread, :id => 2309, :restoration => 4 -append_food :name => :cooked_meat, :id => 2142, :restoration => 3 -append_food :name => :cooked_chicken, :id => 2140, :restoration => 3 -append_food :name => :ugthanki_meat, :id => 1861, :restoration => 3 +food :name => :bread, :id => 2309, :restoration => 4 +food :name => :cooked_meat, :id => 2142, :restoration => 3 +food :name => :cooked_chicken, :id => 2140, :restoration => 3 +food :name => :ugthanki_meat, :id => 1861, :restoration => 3 -append_food :name => :anchovies, :id => 319, :restoration => 1 -append_food :name => :shrimps, :id => 315, :restoration => 3 -append_food :name => :sardine, :id => 325, :restoration => 3 -append_food :name => :herring, :id => 347, :restoration => 5 -append_food :name => :mackeral, :id => 355, :restoration => 5 -append_food :name => :trout, :id => 333, :restoration => 7 -append_food :name => :cod, :id => 339, :restoration => 7 -append_food :name => :pike, :id => 351, :restoration => 8 -append_food :name => :salmon, :id => 329, :restoration => 9 -append_food :name => :tuna, :id => 361, :restoration => 10 -append_food :name => :lobster, :id => 379, :restoration => 12 -append_food :name => :bass, :id => 365, :restoration => 13 -append_food :name => :swordfish, :id => 373, :restoration => 14 -append_food :name => :monkfish, :id => 7946, :restoration => 16 -append_food :name => :shark, :id => 385, :restoration => 20 -append_food :name => :sea_turtle, :id => 397, :restoration => 21 -append_food :name => :manta_ray, :id => 391, :restoration => 22 \ No newline at end of file +food :name => :anchovies, :id => 319, :restoration => 1 +food :name => :shrimps, :id => 315, :restoration => 3 +food :name => :sardine, :id => 325, :restoration => 3 +food :name => :herring, :id => 347, :restoration => 5 +food :name => :mackeral, :id => 355, :restoration => 5 +food :name => :trout, :id => 333, :restoration => 7 +food :name => :cod, :id => 339, :restoration => 7 +food :name => :pike, :id => 351, :restoration => 8 +food :name => :salmon, :id => 329, :restoration => 9 +food :name => :tuna, :id => 361, :restoration => 10 +food :name => :lobster, :id => 379, :restoration => 12 +food :name => :bass, :id => 365, :restoration => 13 +food :name => :swordfish, :id => 373, :restoration => 14 +food :name => :monkfish, :id => 7946, :restoration => 16 +food :name => :shark, :id => 385, :restoration => 20 +food :name => :sea_turtle, :id => 397, :restoration => 21 +food :name => :manta_ray, :id => 391, :restoration => 22 + +food :name => :cake, :id => 1891, :restoration => 4, :replace => 1893 +food :name => :cake, :id => 1893, :restoration => 4, :replace => 1895 +food :name => :cake, :id => 1895, :restoration => 4 + +food :name => :chocolate_cake, :id => 1897, :restoration => 5, :replace => 1899 +food :name => :chocolate_cake, :id => 1899, :restoration => 5, :replace => 1901 +food :name => :chocolate_cake, :id => 1901, :restoration => 5 + +food :name => :plain_pizza, :id => 2289, :restoration => 7, :replace => 2291 +food :name => :plain_pizza, :id => 2291, :restoration => 7 + +food :name => :meat_pizza, :id => 2293, :restoration => 8, :replace => 2295 +food :name => :meat_pizza, :id => 2295, :restoration => 8 + +food :name => :anchovy_pizza, :id => 2297, :restoration => 9, :replace => 2299 +food :name => :anchovy_pizza, :id => 2299, :restoration => 9 + +food :name => :pineapple_pizza, :id => 2301, :restoration => 11, :replace => 2303 +food :name => :pineapple_pizza, :id => 2303, :restoration => 11 + +food :name => :redberry_pie, :id => 2325, :restoration => 5, :replace => 2333, :delay => 1 +food :name => :redberry_pie, :id => 2333, :restoration => 5, :delay => 1 + +food :name => :meat_pie, :id => 2327, :restoration => 6, :replace => 2331, :delay => 1 +food :name => :meat_pie, :id => 2331, :restoration => 6, :delay => 1 + +food :name => :apple_pie, :id => 2323, :restoration => 7, :replace => 2335, :delay => 1 +food :name => :apple_pie, :id => 2335, :restoration => 7, :delay => 1 From be4a4ea7c9466f82993ef43896baa4ea6151daa4 Mon Sep 17 00:00:00 2001 From: Ryley Kimmel Date: Thu, 26 Feb 2015 17:26:23 -0500 Subject: [PATCH 12/59] Add default dependencies tag to the consumable plugin. --- data/plugins/consumables/plugin.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/data/plugins/consumables/plugin.xml b/data/plugins/consumables/plugin.xml index 8acb8325..85c2535a 100644 --- a/data/plugins/consumables/plugin.xml +++ b/data/plugins/consumables/plugin.xml @@ -13,4 +13,5 @@ + \ No newline at end of file From 0b6b6ccd03d827c775525d98b3717d5eca071204 Mon Sep 17 00:00:00 2001 From: Major- Date: Thu, 26 Feb 2015 22:32:59 +0000 Subject: [PATCH 13/59] Move potion constants into a module. --- data/plugins/consumables/potions.rb | 15 +++++++++++---- data/plugins/skill/herblore/potion.rb | 2 ++ 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/data/plugins/consumables/potions.rb b/data/plugins/consumables/potions.rb index 3ec4c8a0..71505929 100644 --- a/data/plugins/consumables/potions.rb +++ b/data/plugins/consumables/potions.rb @@ -4,14 +4,21 @@ java_import 'org.apollo.game.model.entity.Skill' private -DRINK_POTION_SOUND = 334 -EMPTY_VIAL_ID = 229 +module Constants + + # The sound made when drinking a potion. + DRINK_POTION_SOUND = 334 + + # The id of an empty vial. + EMPTY_VIAL_ID = 229 + +end # A drinkable potion. class Potion < Consumable def initialize(id, name, doses) - super(name, id, DRINK_POTION_SOUND) + super(name, id, Constants::DRINK_POTION_SOUND) @doses = doses end @@ -24,7 +31,7 @@ class Potion < Consumable player.send_message("You have #{ @doses.length - index } dose#{ "s" unless index == 3 } of potion left.", true) else player.send_message('You drink the last of your potion.', true) - player.inventory.add(EMPTY_VIAL_ID) + player.inventory.add(Constants::EMPTY_VIAL_ID) end drink(player) diff --git a/data/plugins/skill/herblore/potion.rb b/data/plugins/skill/herblore/potion.rb index 1603f0a1..b99415be 100644 --- a/data/plugins/skill/herblore/potion.rb +++ b/data/plugins/skill/herblore/potion.rb @@ -7,6 +7,8 @@ java_import 'org.apollo.game.model.def.ItemDefinition' java_import 'org.apollo.game.model.inter.EnterAmountListener' java_import 'org.apollo.game.model.inter.dialogue.DialogueAdapter' +private + WATER_VIAL_ID = 227 EMPTY_VIAL_ID = 229 From ac70cdeef40f87d3dfde6fb98dd3b381e7ccae94 Mon Sep 17 00:00:00 2001 From: Ryley Kimmel Date: Thu, 26 Feb 2015 19:27:57 -0500 Subject: [PATCH 14/59] Fix a typo within the bootstrap. --- data/plugins/bootstrap.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/plugins/bootstrap.rb b/data/plugins/bootstrap.rb index 41224dbc..39a74c15 100644 --- a/data/plugins/bootstrap.rb +++ b/data/plugins/bootstrap.rb @@ -80,7 +80,7 @@ class ProcLogoutListener end -# An MessageHandler which executes a Proc object with three arguments: the chain +# A MessageHandler which executes a Proc object with three arguments: the chain # context, the player and the message. class ProcMessageHandler < MessageHandler From b4cc7aa2bd84a277a4e85a6b0d697108f8eeaac9 Mon Sep 17 00:00:00 2001 From: Major- Date: Fri, 27 Feb 2015 03:00:08 +0000 Subject: [PATCH 15/59] Fix rather serious bug from moving the location the GameSession was set. --- .../impl/PlayerDesignMessageHandler.java | 2 +- src/org/apollo/game/model/entity/Player.java | 122 +++++++++--------- src/org/apollo/net/session/LoginSession.java | 7 +- 3 files changed, 66 insertions(+), 65 deletions(-) diff --git a/src/org/apollo/game/message/handler/impl/PlayerDesignMessageHandler.java b/src/org/apollo/game/message/handler/impl/PlayerDesignMessageHandler.java index 96dfa71a..7c4db500 100644 --- a/src/org/apollo/game/message/handler/impl/PlayerDesignMessageHandler.java +++ b/src/org/apollo/game/message/handler/impl/PlayerDesignMessageHandler.java @@ -16,7 +16,7 @@ public final class PlayerDesignMessageHandler extends MessageHandler queuedMessages = new ArrayDeque<>(); - /** - * A flag indicating if the sector changed in the last cycle. - */ - private transient boolean sectorChanged = false; - /** * The player's run energy. */ @@ -188,6 +168,11 @@ public final class Player extends Mob { */ private ScreenBrightness screenBrightness = ScreenBrightness.NORMAL; + /** + * A flag indicating if the sector changed in the last cycle. + */ + private transient boolean sectorChanged = false; + /** * The {@link GameSession} currently attached to this {@link Player}. */ @@ -263,6 +248,16 @@ public final class Player extends Mob { } } + @Override + public boolean equals(Object obj) { + if (obj instanceof Player) { + Player other = (Player) obj; + return credentials.equals(other.credentials); + } + + return false; + } + /** * Sets the excessive npcs flag. */ @@ -355,11 +350,6 @@ public final class Player extends Mob { return EntityType.PLAYER; } - @Override - public int getInteractionIndex() { - return getIndex() | 0x8000; - } - /** * Gets this player's friend chat {@link PrivacyState}. * @@ -387,6 +377,11 @@ public final class Player extends Mob { return ignores; } + @Override + public int getInteractionIndex() { + return getIndex() | 0x8000; + } + /** * Gets this player's interface set. * @@ -495,6 +490,11 @@ public final class Player extends Mob { return worldId; } + @Override + public int hashCode() { + return credentials.hashCode(); + } + /** * Indicates whether or not the player with the specified username is on this player's ignore list. * @@ -680,6 +680,30 @@ public final class Player extends Mob { } } + /** + * Sends the initial messages. + */ + public void sendInitialMessages() { + blockSet.add(SynchronizationBlock.createAppearanceBlock(this)); + send(new IdAssignmentMessage(index, members)); // TODO should this be sent when we reconnect? + sendMessage("Welcome to RuneScape."); + if (newPlayer) { + interfaceSet.openWindow(InterfaceConstants.AVATAR_DESIGN); + } + + int[] tabs = InterfaceConstants.DEFAULT_INVENTORY_TABS; + for (int tab = 0; tab < tabs.length; tab++) { + send(new SwitchTabInterfaceMessage(tab, tabs[tab])); + } + + inventory.forceRefresh(); + equipment.forceRefresh(); + bank.forceRefresh(); + skillSet.forceRefresh(); + + World.getWorld().getLoginDispatcher().dispatch(this); + } + /** * Sends a message to the player. * @@ -833,15 +857,6 @@ public final class Player extends Mob { this.privilegeLevel = privilegeLevel; } - /** - * Sets the sector changed flag. - * - * @param sectorChanged A flag indicating if the sector has changed. - */ - public void setSectorChanged(boolean sectorChanged) { - this.sectorChanged = sectorChanged; - } - /** * Sets the player's run energy. TODO make this an attribute? * @@ -861,18 +876,22 @@ public final class Player extends Mob { this.screenBrightness = brightness; } + /** + * Sets the sector changed flag. + * + * @param sectorChanged A flag indicating if the sector has changed. + */ + public void setSectorChanged(boolean sectorChanged) { + this.sectorChanged = sectorChanged; + } + /** * Sets the player's {@link GameSession}. * * @param session The player's {@link GameSession}. - * @param reconnecting The reconnecting flag. */ - public void setSession(GameSession session, boolean reconnecting) { + public void setSession(GameSession session) { this.session = session; - if (!reconnecting) { - sendInitialMessages(); - } - blockSet.add(SynchronizationBlock.createAppearanceBlock(this)); } /** @@ -982,27 +1001,4 @@ public final class Player extends Mob { skillSet.addListener(new LevelUpSkillListener(this)); } - /** - * Sends the initial messages. - */ - private void sendInitialMessages() { - send(new IdAssignmentMessage(index, members)); // TODO should this be sent when we reconnect? - sendMessage("Welcome to RuneScape."); - if (!newPlayer) { - interfaceSet.openWindow(InterfaceConstants.AVATAR_DESIGN); - } - - int[] tabs = InterfaceConstants.DEFAULT_INVENTORY_TABS; - for (int tab = 0; tab < tabs.length; tab++) { - send(new SwitchTabInterfaceMessage(tab, tabs[tab])); - } - - inventory.forceRefresh(); - equipment.forceRefresh(); - bank.forceRefresh(); - skillSet.forceRefresh(); - - World.getWorld().getLoginDispatcher().dispatch(this); - } - } \ No newline at end of file diff --git a/src/org/apollo/net/session/LoginSession.java b/src/org/apollo/net/session/LoginSession.java index 827249d0..4f2b160d 100644 --- a/src/org/apollo/net/session/LoginSession.java +++ b/src/org/apollo/net/session/LoginSession.java @@ -97,7 +97,7 @@ public final class LoginSession extends Session { rights = player.getPrivilegeLevel().toInteger(); GameSession session = new GameSession(channel, serverContext, player); - RegistrationStatus registration = service.registerPlayer(player, session, request.isReconnecting()); + RegistrationStatus registration = service.registerPlayer(player, session); if (registration != RegistrationStatus.OK) { optional = Optional.empty(); @@ -109,6 +109,7 @@ public final class LoginSession extends Session { } ChannelFuture future = channel.writeAndFlush(new LoginResponse(status, rights, flagged)); + destroy(); if (optional.isPresent()) { @@ -129,6 +130,10 @@ public final class LoginSession extends Session { } else { future.addListener(ChannelFutureListener.CLOSE); } + + if (optional.isPresent()) { + optional.get().sendInitialMessages(); + } } @Override From 6ce4fe198a65fd8ea33a8d628544ed3dfaa92639 Mon Sep 17 00:00:00 2001 From: Ryley Kimmel Date: Thu, 26 Feb 2015 22:11:32 -0500 Subject: [PATCH 16/59] Format author tag, for consistency with other authors. --- data/plugins/consumables/plugin.xml | 2 +- src/org/apollo/game/message/handler/impl/EquipItemHandler.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/data/plugins/consumables/plugin.xml b/data/plugins/consumables/plugin.xml index 85c2535a..50f2ea90 100644 --- a/data/plugins/consumables/plugin.xml +++ b/data/plugins/consumables/plugin.xml @@ -6,7 +6,7 @@ Adds support for consumables (e.g. potions, food). Major - Ryley Kimmel + Ryley diff --git a/src/org/apollo/game/message/handler/impl/EquipItemHandler.java b/src/org/apollo/game/message/handler/impl/EquipItemHandler.java index 8142f89d..a3628e6b 100644 --- a/src/org/apollo/game/message/handler/impl/EquipItemHandler.java +++ b/src/org/apollo/game/message/handler/impl/EquipItemHandler.java @@ -17,7 +17,7 @@ import org.apollo.util.LanguageUtil; * * @author Major * @author Graham - * @author Ryley Kimmel + * @author Ryley */ public final class EquipItemHandler extends MessageHandler { From b7edf786a5fd81df62d882bc77f08e281d747a98 Mon Sep 17 00:00:00 2001 From: Ryley Kimmel Date: Thu, 26 Feb 2015 22:11:59 -0500 Subject: [PATCH 17/59] Formatted and cleaned up the MessageHandlerChain. --- .../message/handler/MessageHandlerChain.java | 35 ++++++++----------- .../handler/MessageHandlerContext.java | 25 +++++++++++-- 2 files changed, 36 insertions(+), 24 deletions(-) diff --git a/src/org/apollo/game/message/handler/MessageHandlerChain.java b/src/org/apollo/game/message/handler/MessageHandlerChain.java index c3c9942c..96e20db5 100644 --- a/src/org/apollo/game/message/handler/MessageHandlerChain.java +++ b/src/org/apollo/game/message/handler/MessageHandlerChain.java @@ -1,5 +1,9 @@ package org.apollo.game.message.handler; +import java.util.ArrayDeque; +import java.util.Arrays; +import java.util.Deque; + import org.apollo.game.message.Message; import org.apollo.game.model.entity.Player; @@ -7,6 +11,7 @@ import org.apollo.game.model.entity.Player; * A chain of message handlers. * * @author Graham + * @author Ryley * @param The type of message handled by this chain. */ public final class MessageHandlerChain { @@ -14,7 +19,7 @@ public final class MessageHandlerChain { /** * The handlers. */ - private MessageHandler[] handlers; + private final Deque> handlers; /** * Creates the message handler chain. @@ -23,7 +28,7 @@ public final class MessageHandlerChain { */ @SafeVarargs public MessageHandlerChain(MessageHandler... handlers) { - this.handlers = handlers; + this.handlers = new ArrayDeque<>(Arrays.asList(handlers)); } /** @@ -31,36 +36,24 @@ public final class MessageHandlerChain { * * @param handler The handler. */ - @SuppressWarnings("unchecked") public void addLast(MessageHandler handler) { - MessageHandler[] old = handlers; - handlers = new MessageHandler[old.length + 1]; - System.arraycopy(old, 0, handlers, 0, old.length); - handlers[old.length] = handler; + handlers.addLast(handler); } /** - * Handles the message, passing it down the chain until the chain is broken or the message reaches the end of the - * chain. + * Handles the message, passing it down the chain until the chain is broken + * or the message reaches the end of the chain. * * @param player The player. * @param message The message. */ public void handle(Player player, M message) { - final boolean[] running = new boolean[1]; - running[0] = true; - - MessageHandlerContext ctx = new MessageHandlerContext() { - - @Override - public void breakHandlerChain() { - running[0] = false; - } - }; + MessageHandlerContext context = new MessageHandlerContext(); for (MessageHandler handler : handlers) { - handler.handle(ctx, player, message); - if (!running[0]) { + handler.handle(context, player, message); + + if (context.isBroken()) { break; } } diff --git a/src/org/apollo/game/message/handler/MessageHandlerContext.java b/src/org/apollo/game/message/handler/MessageHandlerContext.java index 8658e1fa..6660d1e2 100644 --- a/src/org/apollo/game/message/handler/MessageHandlerContext.java +++ b/src/org/apollo/game/message/handler/MessageHandlerContext.java @@ -1,15 +1,34 @@ package org.apollo.game.message.handler; /** - * Provides operations specific to a {@link MessageHandler} in a {@link MessageHandlerChain}. + * Provides operations specific to a {@link MessageHandler} in a + * {@link MessageHandlerChain}. * * @author Graham + * @author Ryley */ -public abstract class MessageHandlerContext { +public final class MessageHandlerContext { + + /** + * Denotes whether or not this handler chain is broken. + */ + private boolean broken; /** * Breaks the handler chain. */ - public abstract void breakHandlerChain(); + public void breakHandlerChain() { + broken = true; + } + + /** + * Returns whether or not this handler chain is broken. + * + * @return {@code true} if this handler chain is broken, otherwise + * {@code false}. + */ + public boolean isBroken() { + return broken; + } } \ No newline at end of file From 7e8deb62f1b2ce723213018148a89ade65ca80ac Mon Sep 17 00:00:00 2001 From: Major- Date: Fri, 27 Feb 2015 03:18:00 +0000 Subject: [PATCH 18/59] Resolve compilation error. --- src/org/apollo/game/GameService.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/org/apollo/game/GameService.java b/src/org/apollo/game/GameService.java index 3f647950..efdbab2a 100644 --- a/src/org/apollo/game/GameService.java +++ b/src/org/apollo/game/GameService.java @@ -152,14 +152,13 @@ public final class GameService extends Service { * * @param player The Player. * @param session The {@link GameSession} of the Player. - * @param reconnecting The reconnecting flag. * @return A {@link RegistrationStatus}. */ - public RegistrationStatus registerPlayer(Player player, GameSession session, boolean reconnecting) { + public RegistrationStatus registerPlayer(Player player, GameSession session) { synchronized (this) { RegistrationStatus status = World.getWorld().register(player); if (status == RegistrationStatus.OK) { - player.setSession(session, reconnecting); + player.setSession(session); } return status; From 78136c4eaa64799f81094f00cac0b7c413efc752 Mon Sep 17 00:00:00 2001 From: Major- Date: Fri, 27 Feb 2015 03:20:30 +0000 Subject: [PATCH 19/59] Add custom Event support. --- .../apollo/game/model/entity/event/Event.java | 10 ++++ .../game/model/entity/event/EventContext.java | 31 ++++++++++++ .../model/entity/event/EventListener.java | 21 +++++++++ .../entity/event/EventListenerChain.java | 47 +++++++++++++++++++ .../entity/event/EventListenerChainSet.java | 40 ++++++++++++++++ .../game/model/entity/event/package-info.java | 4 ++ 6 files changed, 153 insertions(+) create mode 100644 src/org/apollo/game/model/entity/event/Event.java create mode 100644 src/org/apollo/game/model/entity/event/EventContext.java create mode 100644 src/org/apollo/game/model/entity/event/EventListener.java create mode 100644 src/org/apollo/game/model/entity/event/EventListenerChain.java create mode 100644 src/org/apollo/game/model/entity/event/EventListenerChainSet.java create mode 100644 src/org/apollo/game/model/entity/event/package-info.java diff --git a/src/org/apollo/game/model/entity/event/Event.java b/src/org/apollo/game/model/entity/event/Event.java new file mode 100644 index 00000000..cf349844 --- /dev/null +++ b/src/org/apollo/game/model/entity/event/Event.java @@ -0,0 +1,10 @@ +package org.apollo.game.model.entity.event; + +/** + * A type of event that may occur in the game world. + * + * @author Major + */ +public abstract class Event { + +} \ No newline at end of file diff --git a/src/org/apollo/game/model/entity/event/EventContext.java b/src/org/apollo/game/model/entity/event/EventContext.java new file mode 100644 index 00000000..f9568779 --- /dev/null +++ b/src/org/apollo/game/model/entity/event/EventContext.java @@ -0,0 +1,31 @@ +package org.apollo.game.model.entity.event; + +/** + * The context of an {@link Event}. + * + * @author Major + */ +final class EventContext { + + /** + * Indicates whether or not the Event chain has been terminated. + */ + private boolean terminated; + + /** + * Terminates the Event chain. + */ + public void terminate() { + terminated = true; + } + + /** + * Returns whether or not the Event chain has been terminated. + * + * @return {@code true} if the Event chain has been terminated, otherwise {@code false}. + */ + public boolean terminated() { + return terminated; + } + +} \ No newline at end of file diff --git a/src/org/apollo/game/model/entity/event/EventListener.java b/src/org/apollo/game/model/entity/event/EventListener.java new file mode 100644 index 00000000..46ad7a1c --- /dev/null +++ b/src/org/apollo/game/model/entity/event/EventListener.java @@ -0,0 +1,21 @@ +package org.apollo.game.model.entity.event; + +/** + * A listener for an {@link Event} that may occur in the game world. + * + * @author Major + * + * @param The type of Event. + */ +@FunctionalInterface +public interface EventListener { + + /** + * Handles the {@link Event} that occurred. + * + * @param event The Event. + * @param context The {@link EventContext}. + */ + public void handle(E event, EventContext context); + +} \ No newline at end of file diff --git a/src/org/apollo/game/model/entity/event/EventListenerChain.java b/src/org/apollo/game/model/entity/event/EventListenerChain.java new file mode 100644 index 00000000..c72a09d8 --- /dev/null +++ b/src/org/apollo/game/model/entity/event/EventListenerChain.java @@ -0,0 +1,47 @@ +package org.apollo.game.model.entity.event; + +import java.util.ArrayList; +import java.util.List; + +/** + * A chain of {@link EventListener}s. + * + * @author Major + * @param The type of {@link Event} the listeners in this chain listen for. + */ +final class EventListenerChain { + + /** + * The List of EventListeners. + */ + private final List> listeners = new ArrayList<>(); + + /** + * Adds an {@link EventListener} to this chain. + * + * @param listener The EventListener to add. + */ + public void addListener(EventListener listener) { + listeners.add(listener); + } + + /** + * Notifies each {@link EventListener} in this chain that an {@link Event} has occurred. + * + * @param event The event. + * @return {@code true} if the Event should continue on with its outcome, {@code false} if not. + */ + public boolean notify(E event) { + EventContext context = new EventContext(); + for (EventListener listener : listeners) { + listener.handle(event, context); + + if (context.terminated()) { + return false; + } + } + + return false; + } + +} \ No newline at end of file diff --git a/src/org/apollo/game/model/entity/event/EventListenerChainSet.java b/src/org/apollo/game/model/entity/event/EventListenerChainSet.java new file mode 100644 index 00000000..b8d327a4 --- /dev/null +++ b/src/org/apollo/game/model/entity/event/EventListenerChainSet.java @@ -0,0 +1,40 @@ +package org.apollo.game.model.entity.event; + +import java.util.HashMap; +import java.util.Map; + +/** + * A set of {@link EventListenerChain}s. + * + * @author Major + */ +public final class EventListenerChainSet { + + /** + * The Map of Event Classes to EventListenerChains. + */ + private final Map, EventListenerChain> chains = new HashMap<>(); + + /** + * Notifies the appropriate {@link EventListenerChain} that an {@link Event} has occurred. + * + * @param event The Event. + * @return {@code true} if the Event should continue on with its outcome, {@code false} if not. + */ + public boolean notify(E event) { + @SuppressWarnings("unchecked") + EventListenerChain chain = (EventListenerChain) chains.get(event); + return chain.notify(event); + } + + /** + * Places the {@link EventListenerChain} into this set. + * + * @param clazz The {@link Class} to associate the EventListenerChain with. + * @param chain The EventListenerChain. + */ + public void putListenerChain(Class clazz, EventListenerChain chain) { + chains.put(clazz, chain); + } + +} \ No newline at end of file diff --git a/src/org/apollo/game/model/entity/event/package-info.java b/src/org/apollo/game/model/entity/event/package-info.java new file mode 100644 index 00000000..6b10ac54 --- /dev/null +++ b/src/org/apollo/game/model/entity/event/package-info.java @@ -0,0 +1,4 @@ +/** + * Contains event-related classes. + */ +package org.apollo.game.model.entity.event; \ No newline at end of file From d60075dcf6831fd88ec0f7b1134de850a7e81fcf Mon Sep 17 00:00:00 2001 From: Major- Date: Fri, 27 Feb 2015 03:21:47 +0000 Subject: [PATCH 20/59] Rename previously-named classes from 'Overlay' to 'Sidebar', add actual Overlay interface support. --- ....java => OpenInterfaceSidebarMessage.java} | 24 +++---- .../game/message/impl/OpenOverlayMessage.java | 2 +- .../game/message/impl/OpenSidebarMessage.java | 35 ++++++++++ .../apollo/game/model/inter/InterfaceSet.java | 67 +++++++++++-------- ...> OpenInterfaceSidebarMessageEncoder.java} | 10 +-- .../r317/OpenOverlayMessageEncoder.java | 2 +- .../r317/OpenSidebarMessageEncoder.java | 24 +++++++ .../apollo/net/release/r317/Release317.java | 6 +- ...> OpenInterfaceSidebarMessageEncoder.java} | 10 +-- .../r377/OpenOverlayMessageEncoder.java | 6 +- .../r377/OpenSidebarMessageEncoder.java | 25 +++++++ .../apollo/net/release/r377/Release377.java | 6 +- 12 files changed, 157 insertions(+), 60 deletions(-) rename src/org/apollo/game/message/impl/{OpenInterfaceOverlayMessage.java => OpenInterfaceSidebarMessage.java} (54%) create mode 100644 src/org/apollo/game/message/impl/OpenSidebarMessage.java rename src/org/apollo/net/release/r317/{OpenInterfaceOverlayMessageEncoder.java => OpenInterfaceSidebarMessageEncoder.java} (58%) create mode 100644 src/org/apollo/net/release/r317/OpenSidebarMessageEncoder.java rename src/org/apollo/net/release/r377/{OpenInterfaceOverlayMessageEncoder.java => OpenInterfaceSidebarMessageEncoder.java} (64%) create mode 100644 src/org/apollo/net/release/r377/OpenSidebarMessageEncoder.java diff --git a/src/org/apollo/game/message/impl/OpenInterfaceOverlayMessage.java b/src/org/apollo/game/message/impl/OpenInterfaceSidebarMessage.java similarity index 54% rename from src/org/apollo/game/message/impl/OpenInterfaceOverlayMessage.java rename to src/org/apollo/game/message/impl/OpenInterfaceSidebarMessage.java index 1d34521d..66775c5d 100644 --- a/src/org/apollo/game/message/impl/OpenInterfaceOverlayMessage.java +++ b/src/org/apollo/game/message/impl/OpenInterfaceSidebarMessage.java @@ -3,11 +3,11 @@ package org.apollo.game.message.impl; import org.apollo.game.message.Message; /** - * A {@link Message} sent to the client to open an interface and temporary overlay. + * A {@link Message} sent to the client to open an interface and a sidebar. * * @author Graham */ -public final class OpenInterfaceOverlayMessage extends Message { +public final class OpenInterfaceSidebarMessage extends Message { /** * The interface id. @@ -15,19 +15,19 @@ public final class OpenInterfaceOverlayMessage extends Message { private final int interfaceId; /** - * The overlay id. + * The sidebar id. */ - private final int overlayId; + private final int sidebarId; /** - * Creates the open interface overlay message. + * Creates the OpenInterfaceSidebarMessage. * * @param interfaceId The interface id. - * @param overlayId The overlay id. + * @param sidebarId The sidebar id. */ - public OpenInterfaceOverlayMessage(int interfaceId, int overlayId) { + public OpenInterfaceSidebarMessage(int interfaceId, int sidebarId) { this.interfaceId = interfaceId; - this.overlayId = overlayId; + this.sidebarId = sidebarId; } /** @@ -40,12 +40,12 @@ public final class OpenInterfaceOverlayMessage extends Message { } /** - * Gets the overlay id. + * Gets the sidebar id. * - * @return The overlay id. + * @return The sidebar id. */ - public int getOverlayId() { - return overlayId; + public int getSidebarId() { + return sidebarId; } } \ No newline at end of file diff --git a/src/org/apollo/game/message/impl/OpenOverlayMessage.java b/src/org/apollo/game/message/impl/OpenOverlayMessage.java index 90ad7dbc..79c029d6 100644 --- a/src/org/apollo/game/message/impl/OpenOverlayMessage.java +++ b/src/org/apollo/game/message/impl/OpenOverlayMessage.java @@ -15,7 +15,7 @@ public final class OpenOverlayMessage extends Message { private final int overlayId; /** - * Creates the open interface overlay message. + * Creates the OpenSidebarMessage. * * @param overlayId The overlay id. */ diff --git a/src/org/apollo/game/message/impl/OpenSidebarMessage.java b/src/org/apollo/game/message/impl/OpenSidebarMessage.java new file mode 100644 index 00000000..1f3a41d8 --- /dev/null +++ b/src/org/apollo/game/message/impl/OpenSidebarMessage.java @@ -0,0 +1,35 @@ +package org.apollo.game.message.impl; + +import org.apollo.game.message.Message; + +/** + * A {@link Message} sent to the client to open a sidebar interface. + * + * @author Major + */ +public final class OpenSidebarMessage extends Message { + + /** + * The sidebar id. + */ + private final int sidebarId; + + /** + * Creates the OpenSidebarMessage. + * + * @param sidebarId The sidebar id. + */ + public OpenSidebarMessage(int sidebarId) { + this.sidebarId = sidebarId; + } + + /** + * Gets the sidebar id. + * + * @return The sidebar id. + */ + public int getSidebarId() { + return sidebarId; + } + +} \ No newline at end of file diff --git a/src/org/apollo/game/model/inter/InterfaceSet.java b/src/org/apollo/game/model/inter/InterfaceSet.java index b2178eac..6b9dfeec 100644 --- a/src/org/apollo/game/model/inter/InterfaceSet.java +++ b/src/org/apollo/game/model/inter/InterfaceSet.java @@ -8,8 +8,9 @@ import org.apollo.game.message.impl.CloseInterfaceMessage; import org.apollo.game.message.impl.EnterAmountMessage; import org.apollo.game.message.impl.OpenDialogueInterfaceMessage; import org.apollo.game.message.impl.OpenInterfaceMessage; -import org.apollo.game.message.impl.OpenInterfaceOverlayMessage; +import org.apollo.game.message.impl.OpenInterfaceSidebarMessage; import org.apollo.game.message.impl.OpenOverlayMessage; +import org.apollo.game.message.impl.OpenSidebarMessage; import org.apollo.game.model.entity.Player; import org.apollo.game.model.inter.dialogue.DialogueListener; import org.apollo.game.model.inv.InventoryListener; @@ -172,6 +173,42 @@ public final class InterfaceSet { player.send(new EnterAmountMessage()); } + /** + * Opens an overlay interface. + * + * @param overlay The overlay id. + */ + public void openOverlay(int overlay) { + interfaces.put(InterfaceType.OVERLAY, overlay); + player.send(new OpenOverlayMessage(overlay)); + } + + /** + * Opens an sidebar interface. + * + * @param sidebar The sidebar id. + */ + public void openSidebar(int sidebar) { + closeAndNotify(); + interfaces.put(InterfaceType.SIDEBAR, sidebar); + + player.send(new OpenSidebarMessage(sidebar)); + } + + /** + * Opens an sidebar interface with the specified {@link InventoryListener}. + * + * @param listener The listener. + * @param sidebar The sidebar id. + */ + public void openSidebar(InterfaceListener listener, int sidebar) { + closeAndNotify(); + this.listener = Optional.ofNullable(listener); + interfaces.put(InterfaceType.SIDEBAR, sidebar); + + player.send(new OpenSidebarMessage(sidebar)); + } + /** * Opens a window. * @@ -219,33 +256,7 @@ public final class InterfaceSet { interfaces.put(InterfaceType.WINDOW, windowId); interfaces.put(InterfaceType.SIDEBAR, sidebarId); - player.send(new OpenInterfaceOverlayMessage(windowId, sidebarId)); - } - - /** - * Opens an overlay interface. - * - * @param overlay The overlay id. - */ - public void openOverlay(int overlay) { - closeAndNotify(); - interfaces.put(InterfaceType.OVERLAY, overlay); - - player.send(new OpenOverlayMessage(overlay)); - } - - /** - * Opens an overlay interface with the specified {@link InventoryListener}. - * - * @param listener The listener. - * @param overlay The overlay id. - */ - public void openOverlay(InterfaceListener listener, int overlay) { - closeAndNotify(); - this.listener = Optional.ofNullable(listener); - interfaces.put(InterfaceType.OVERLAY, overlay); - - player.send(new OpenOverlayMessage(overlay)); + player.send(new OpenInterfaceSidebarMessage(windowId, sidebarId)); } /** diff --git a/src/org/apollo/net/release/r317/OpenInterfaceOverlayMessageEncoder.java b/src/org/apollo/net/release/r317/OpenInterfaceSidebarMessageEncoder.java similarity index 58% rename from src/org/apollo/net/release/r317/OpenInterfaceOverlayMessageEncoder.java rename to src/org/apollo/net/release/r317/OpenInterfaceSidebarMessageEncoder.java index 1a1d18c9..a13edd65 100644 --- a/src/org/apollo/net/release/r317/OpenInterfaceOverlayMessageEncoder.java +++ b/src/org/apollo/net/release/r317/OpenInterfaceSidebarMessageEncoder.java @@ -1,6 +1,6 @@ package org.apollo.net.release.r317; -import org.apollo.game.message.impl.OpenInterfaceOverlayMessage; +import org.apollo.game.message.impl.OpenInterfaceSidebarMessage; import org.apollo.net.codec.game.DataTransformation; import org.apollo.net.codec.game.DataType; import org.apollo.net.codec.game.GamePacket; @@ -8,17 +8,17 @@ import org.apollo.net.codec.game.GamePacketBuilder; import org.apollo.net.release.MessageEncoder; /** - * A {@link MessageEncoder} for the {@link OpenInterfaceOverlayMessage}. + * A {@link MessageEncoder} for the {@link OpenInterfaceSidebarMessage}. * * @author Graham */ -public final class OpenInterfaceOverlayMessageEncoder extends MessageEncoder { +public final class OpenInterfaceSidebarMessageEncoder extends MessageEncoder { @Override - public GamePacket encode(OpenInterfaceOverlayMessage message) { + public GamePacket encode(OpenInterfaceSidebarMessage message) { GamePacketBuilder builder = new GamePacketBuilder(248); builder.put(DataType.SHORT, DataTransformation.ADD, message.getInterfaceId()); - builder.put(DataType.SHORT, message.getOverlayId()); + builder.put(DataType.SHORT, message.getSidebarId()); return builder.toGamePacket(); } diff --git a/src/org/apollo/net/release/r317/OpenOverlayMessageEncoder.java b/src/org/apollo/net/release/r317/OpenOverlayMessageEncoder.java index f9ff4a8c..73ab99e9 100644 --- a/src/org/apollo/net/release/r317/OpenOverlayMessageEncoder.java +++ b/src/org/apollo/net/release/r317/OpenOverlayMessageEncoder.java @@ -16,7 +16,7 @@ public final class OpenOverlayMessageEncoder extends MessageEncoder { + + @Override + public GamePacket encode(OpenSidebarMessage message) { + GamePacketBuilder builder = new GamePacketBuilder(142); + builder.put(DataType.SHORT, DataOrder.LITTLE, message.getSidebarId()); + return builder.toGamePacket(); + } + +} \ No newline at end of file diff --git a/src/org/apollo/net/release/r317/Release317.java b/src/org/apollo/net/release/r317/Release317.java index e57d1d9e..0f4d3cc0 100644 --- a/src/org/apollo/net/release/r317/Release317.java +++ b/src/org/apollo/net/release/r317/Release317.java @@ -17,8 +17,9 @@ import org.apollo.game.message.impl.LogoutMessage; import org.apollo.game.message.impl.NpcSynchronizationMessage; import org.apollo.game.message.impl.OpenDialogueInterfaceMessage; import org.apollo.game.message.impl.OpenInterfaceMessage; -import org.apollo.game.message.impl.OpenInterfaceOverlayMessage; +import org.apollo.game.message.impl.OpenInterfaceSidebarMessage; import org.apollo.game.message.impl.OpenOverlayMessage; +import org.apollo.game.message.impl.OpenSidebarMessage; import org.apollo.game.message.impl.PlayerSynchronizationMessage; import org.apollo.game.message.impl.PositionMessage; import org.apollo.game.message.impl.PrivacyOptionMessage; @@ -179,7 +180,7 @@ public final class Release317 extends Release { register(UpdateItemsMessage.class, new UpdateItemsMessageEncoder()); register(UpdateSlottedItemsMessage.class, new UpdateSlottedItemsMessageEncoder()); register(UpdateSkillMessage.class, new UpdateSkillMessageEncoder()); - register(OpenInterfaceOverlayMessage.class, new OpenInterfaceOverlayMessageEncoder()); + register(OpenInterfaceSidebarMessage.class, new OpenInterfaceSidebarMessageEncoder()); register(EnterAmountMessage.class, new EnterAmountMessageEncoder()); register(SetWidgetTextMessage.class, new SetWidgetTextMessageEncoder()); register(NpcSynchronizationMessage.class, new NpcSynchronizationMessageEncoder()); @@ -210,6 +211,7 @@ public final class Release317 extends Release { register(SendFriendMessage.class, new SendFriendMessageEncoder()); register(HintIconMessage.class, new HintIconMessageEncoder()); register(FlashTabInterfaceMessage.class, new FlashTabInterfaceMessageEncoder()); + register(OpenSidebarMessage.class, new OpenSidebarMessageEncoder()); register(OpenOverlayMessage.class, new OpenOverlayMessageEncoder()); } } \ No newline at end of file diff --git a/src/org/apollo/net/release/r377/OpenInterfaceOverlayMessageEncoder.java b/src/org/apollo/net/release/r377/OpenInterfaceSidebarMessageEncoder.java similarity index 64% rename from src/org/apollo/net/release/r377/OpenInterfaceOverlayMessageEncoder.java rename to src/org/apollo/net/release/r377/OpenInterfaceSidebarMessageEncoder.java index 2a83cc8c..543c509a 100644 --- a/src/org/apollo/net/release/r377/OpenInterfaceOverlayMessageEncoder.java +++ b/src/org/apollo/net/release/r377/OpenInterfaceSidebarMessageEncoder.java @@ -1,6 +1,6 @@ package org.apollo.net.release.r377; -import org.apollo.game.message.impl.OpenInterfaceOverlayMessage; +import org.apollo.game.message.impl.OpenInterfaceSidebarMessage; import org.apollo.net.codec.game.DataOrder; import org.apollo.net.codec.game.DataTransformation; import org.apollo.net.codec.game.DataType; @@ -9,17 +9,17 @@ import org.apollo.net.codec.game.GamePacketBuilder; import org.apollo.net.release.MessageEncoder; /** - * A {@link MessageEncoder} for the {@link OpenInterfaceOverlayMessage}. + * A {@link MessageEncoder} for the {@link OpenInterfaceSidebarMessage}. * * @author Graham */ -public final class OpenInterfaceOverlayMessageEncoder extends MessageEncoder { +public final class OpenInterfaceSidebarMessageEncoder extends MessageEncoder { @Override - public GamePacket encode(OpenInterfaceOverlayMessage message) { + public GamePacket encode(OpenInterfaceSidebarMessage message) { GamePacketBuilder builder = new GamePacketBuilder(128); builder.put(DataType.SHORT, DataTransformation.ADD, message.getInterfaceId()); - builder.put(DataType.SHORT, DataOrder.LITTLE, DataTransformation.ADD, message.getOverlayId()); + builder.put(DataType.SHORT, DataOrder.LITTLE, DataTransformation.ADD, message.getSidebarId()); return builder.toGamePacket(); } diff --git a/src/org/apollo/net/release/r377/OpenOverlayMessageEncoder.java b/src/org/apollo/net/release/r377/OpenOverlayMessageEncoder.java index e3364138..45d210af 100644 --- a/src/org/apollo/net/release/r377/OpenOverlayMessageEncoder.java +++ b/src/org/apollo/net/release/r377/OpenOverlayMessageEncoder.java @@ -1,8 +1,6 @@ package org.apollo.net.release.r377; import org.apollo.game.message.impl.OpenOverlayMessage; -import org.apollo.net.codec.game.DataOrder; -import org.apollo.net.codec.game.DataTransformation; import org.apollo.net.codec.game.DataType; import org.apollo.net.codec.game.GamePacket; import org.apollo.net.codec.game.GamePacketBuilder; @@ -17,8 +15,8 @@ public final class OpenOverlayMessageEncoder extends MessageEncoder { + + @Override + public GamePacket encode(OpenSidebarMessage message) { + GamePacketBuilder builder = new GamePacketBuilder(246); + builder.put(DataType.SHORT, DataOrder.LITTLE, DataTransformation.ADD, message.getSidebarId()); + return builder.toGamePacket(); + } + +} \ No newline at end of file diff --git a/src/org/apollo/net/release/r377/Release377.java b/src/org/apollo/net/release/r377/Release377.java index 9cee1c14..db4868e7 100644 --- a/src/org/apollo/net/release/r377/Release377.java +++ b/src/org/apollo/net/release/r377/Release377.java @@ -17,8 +17,9 @@ import org.apollo.game.message.impl.LogoutMessage; import org.apollo.game.message.impl.NpcSynchronizationMessage; import org.apollo.game.message.impl.OpenDialogueInterfaceMessage; import org.apollo.game.message.impl.OpenInterfaceMessage; -import org.apollo.game.message.impl.OpenInterfaceOverlayMessage; +import org.apollo.game.message.impl.OpenInterfaceSidebarMessage; import org.apollo.game.message.impl.OpenOverlayMessage; +import org.apollo.game.message.impl.OpenSidebarMessage; import org.apollo.game.message.impl.PlayerSynchronizationMessage; import org.apollo.game.message.impl.PositionMessage; import org.apollo.game.message.impl.PrivacyOptionMessage; @@ -175,7 +176,7 @@ public final class Release377 extends Release { register(UpdateItemsMessage.class, new UpdateItemsMessageEncoder()); register(UpdateSlottedItemsMessage.class, new UpdateSlottedItemsMessageEncoder()); register(UpdateSkillMessage.class, new UpdateSkillMessageEncoder()); - register(OpenInterfaceOverlayMessage.class, new OpenInterfaceOverlayMessageEncoder()); + register(OpenInterfaceSidebarMessage.class, new OpenInterfaceSidebarMessageEncoder()); register(EnterAmountMessage.class, new EnterAmountMessageEncoder()); register(SetWidgetTextMessage.class, new SetWidgetTexMessageEncoder()); register(NpcSynchronizationMessage.class, new NpcSynchronizationMessageEncoder()); @@ -206,6 +207,7 @@ public final class Release377 extends Release { register(SendFriendMessage.class, new SendFriendMessageEncoder()); register(HintIconMessage.class, new HintIconMessageEncoder()); register(FlashTabInterfaceMessage.class, new FlashTabInterfaceMessageEncoder()); + register(OpenSidebarMessage.class, new OpenSidebarMessageEncoder()); register(OpenOverlayMessage.class, new OpenOverlayMessageEncoder()); } From 3d2484c42d5021f5106a500dd614822489b46a0d Mon Sep 17 00:00:00 2001 From: Major- Date: Fri, 27 Feb 2015 03:35:26 +0000 Subject: [PATCH 21/59] Finish custom Events. --- src/org/apollo/game/model/World.java | 35 ++++++++++++++++--- .../entity/event/EventListenerChain.java | 20 +++++++++++ .../entity/event/EventListenerChainSet.java | 8 +++-- 3 files changed, 56 insertions(+), 7 deletions(-) diff --git a/src/org/apollo/game/model/World.java b/src/org/apollo/game/model/World.java index 990a8a40..3374eb10 100644 --- a/src/org/apollo/game/model/World.java +++ b/src/org/apollo/game/model/World.java @@ -27,6 +27,9 @@ import org.apollo.game.model.entity.Entity; import org.apollo.game.model.entity.GameObject; import org.apollo.game.model.entity.Npc; import org.apollo.game.model.entity.Player; +import org.apollo.game.model.entity.event.Event; +import org.apollo.game.model.entity.event.EventListener; +import org.apollo.game.model.entity.event.EventListenerChainSet; import org.apollo.game.scheduling.ScheduledTask; import org.apollo.game.scheduling.Scheduler; import org.apollo.io.EquipmentDefinitionParser; @@ -91,6 +94,11 @@ public final class World { */ private final CommandDispatcher commandDispatcher = new CommandDispatcher(); + /** + * The EventListenerChainSet for this World. + */ + private final EventListenerChainSet events = new EventListenerChainSet(); + /** * The login dispatcher. */ @@ -279,12 +287,13 @@ public final class World { } /** - * Adds entities to sectors in the {@link SectorRepository}. + * Adds an {@link EventListener}, listening for an {@link Event} of the specified type. * - * @param entities The entities. + * @param type The type of the Event. + * @param listener The EventListener. */ - private void placeEntities(Entity... entities) { - Arrays.stream(entities).forEach(entity -> sectors.fromPosition(entity.getPosition()).addEntity(entity)); + public void listenFor(Class type, EventListener listener) { + events.putListener(type, listener); } /** @@ -348,6 +357,15 @@ public final class World { return scheduler.schedule(task); } + /** + * Submits the specified {@link Event}, passing it to the listeners.. + * + * @param event The Event. + */ + public void submit(Event event) { + events.notify(event); + } + /** * Unregisters the specified {@link Npc}. * @@ -382,4 +400,13 @@ public final class World { } } + /** + * Adds entities to sectors in the {@link SectorRepository}. + * + * @param entities The entities. + */ + private void placeEntities(Entity... entities) { + Arrays.stream(entities).forEach(entity -> sectors.fromPosition(entity.getPosition()).addEntity(entity)); + } + } \ No newline at end of file diff --git a/src/org/apollo/game/model/entity/event/EventListenerChain.java b/src/org/apollo/game/model/entity/event/EventListenerChain.java index c72a09d8..b46f8dc9 100644 --- a/src/org/apollo/game/model/entity/event/EventListenerChain.java +++ b/src/org/apollo/game/model/entity/event/EventListenerChain.java @@ -3,6 +3,8 @@ package org.apollo.game.model.entity.event; import java.util.ArrayList; import java.util.List; +import com.google.common.base.MoreObjects; + /** * A chain of {@link EventListener}s. * @@ -16,6 +18,20 @@ final class EventListenerChain { */ private final List> listeners = new ArrayList<>(); + /** + * The Class type of this chain. + */ + private final Class type; + + /** + * Creates the EventListenerChain. + * + * @param type The {@link Class} type of this chain. + */ + public EventListenerChain(Class type) { + this.type = type; + } + /** * Adds an {@link EventListener} to this chain. * @@ -44,4 +60,8 @@ final class EventListenerChain { return false; } + @Override + public String toString() { + return MoreObjects.toStringHelper(this).add("type", type).add("listeners", listeners).toString(); + } } \ No newline at end of file diff --git a/src/org/apollo/game/model/entity/event/EventListenerChainSet.java b/src/org/apollo/game/model/entity/event/EventListenerChainSet.java index b8d327a4..4df75722 100644 --- a/src/org/apollo/game/model/entity/event/EventListenerChainSet.java +++ b/src/org/apollo/game/model/entity/event/EventListenerChainSet.java @@ -31,10 +31,12 @@ public final class EventListenerChainSet { * Places the {@link EventListenerChain} into this set. * * @param clazz The {@link Class} to associate the EventListenerChain with. - * @param chain The EventListenerChain. + * @param listener The EventListenerChain. */ - public void putListenerChain(Class clazz, EventListenerChain chain) { - chains.put(clazz, chain); + public void putListener(Class clazz, EventListener listener) { + @SuppressWarnings("unchecked") + EventListenerChain chain = (EventListenerChain) chains.computeIfAbsent(clazz, EventListenerChain::new); + chain.addListener(listener); } } \ No newline at end of file From 3e4ecb5c730fd0ebd32adcc593065e6cfcf1aa30 Mon Sep 17 00:00:00 2001 From: Major- Date: Fri, 27 Feb 2015 03:36:28 +0000 Subject: [PATCH 22/59] Fix missing return type of World#submit. --- src/org/apollo/game/model/World.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/org/apollo/game/model/World.java b/src/org/apollo/game/model/World.java index 3374eb10..c1cf8898 100644 --- a/src/org/apollo/game/model/World.java +++ b/src/org/apollo/game/model/World.java @@ -361,9 +361,10 @@ public final class World { * Submits the specified {@link Event}, passing it to the listeners.. * * @param event The Event. + * @return {@code true} if the Event should proceed, {@code false} if not. */ - public void submit(Event event) { - events.notify(event); + public boolean submit(Event event) { + return events.notify(event); } /** From 06b6f5fb74a08fcb26da73b2d6a0eea64ca93997 Mon Sep 17 00:00:00 2001 From: Major- Date: Fri, 27 Feb 2015 04:11:08 +0000 Subject: [PATCH 23/59] Move login and logout listening to the new Event system and update plugins to reflect this move, remove previous listening system, fix minor bug in EventListenerChainSet. --- data/plugins/bootstrap.rb | 57 +++++++++---------- data/plugins/chat/private-messaging/friend.rb | 7 ++- data/plugins/skill/runecraft/tiara.rb | 16 +++--- .../apollo/game/login/LoginDispatcher.java | 38 ------------- src/org/apollo/game/login/LoginListener.java | 20 ------- .../apollo/game/login/LogoutDispatcher.java | 38 ------------- src/org/apollo/game/login/LogoutListener.java | 20 ------- src/org/apollo/game/login/package-info.java | 4 -- src/org/apollo/game/model/World.java | 38 +------------ src/org/apollo/game/model/entity/Player.java | 3 +- .../game/model/{entity => }/event/Event.java | 2 +- .../{entity => }/event/EventContext.java | 4 +- .../{entity => }/event/EventListener.java | 2 +- .../event/EventListenerChain.java | 2 +- .../event/EventListenerChainSet.java | 6 +- .../apollo/game/model/event/PlayerEvent.java | 35 ++++++++++++ .../event/impl/CloseInterfacesEvent.java | 23 ++++++++ .../game/model/event/impl/LoginEvent.java | 22 +++++++ .../game/model/event/impl/LogoutEvent.java | 22 +++++++ .../game/model/event/impl/package-info.java | 4 ++ .../{entity => }/event/package-info.java | 2 +- .../apollo/game/model/inter/InterfaceSet.java | 9 ++- src/org/apollo/util/plugin/PluginContext.java | 20 +++---- 23 files changed, 174 insertions(+), 220 deletions(-) delete mode 100644 src/org/apollo/game/login/LoginDispatcher.java delete mode 100644 src/org/apollo/game/login/LoginListener.java delete mode 100644 src/org/apollo/game/login/LogoutDispatcher.java delete mode 100644 src/org/apollo/game/login/LogoutListener.java delete mode 100644 src/org/apollo/game/login/package-info.java rename src/org/apollo/game/model/{entity => }/event/Event.java (72%) rename src/org/apollo/game/model/{entity => }/event/EventContext.java (87%) rename src/org/apollo/game/model/{entity => }/event/EventListener.java (89%) rename src/org/apollo/game/model/{entity => }/event/EventListenerChain.java (97%) rename src/org/apollo/game/model/{entity => }/event/EventListenerChainSet.java (91%) create mode 100644 src/org/apollo/game/model/event/PlayerEvent.java create mode 100644 src/org/apollo/game/model/event/impl/CloseInterfacesEvent.java create mode 100644 src/org/apollo/game/model/event/impl/LoginEvent.java create mode 100644 src/org/apollo/game/model/event/impl/LogoutEvent.java create mode 100644 src/org/apollo/game/model/event/impl/package-info.java rename src/org/apollo/game/model/{entity => }/event/package-info.java (50%) diff --git a/data/plugins/bootstrap.rb b/data/plugins/bootstrap.rb index 39a74c15..9f90a4c5 100644 --- a/data/plugins/bootstrap.rb +++ b/data/plugins/bootstrap.rb @@ -16,10 +16,9 @@ require 'java' java_import 'org.apollo.game.command.CommandListener' java_import 'org.apollo.game.message.handler.MessageHandler' -java_import 'org.apollo.game.login.LoginListener' -java_import 'org.apollo.game.login.LogoutListener' java_import 'org.apollo.game.model.World' java_import 'org.apollo.game.model.entity.Player' +java_import 'org.apollo.game.model.event.EventListener' java_import 'org.apollo.game.model.setting.PrivilegeLevel' java_import 'org.apollo.game.scheduling.ScheduledTask' java_import 'org.apollo.util.plugin.PluginContext' @@ -32,50 +31,43 @@ RIGHTS_STANDARD = PrivilegeLevel::STANDARD # Extends the (Ruby) String class with a method to convert a lower case, # underscore delimited string to camel-case. class String - def camelize + + # Converts a ruby snake_case string to camel-case. + def camelize() gsub(/(?:^|_)(.)/) { $1.upcase } end + end # A CommandListener that executes a Proc object with two arguments: the player and the command. class ProcCommandListener < CommandListener + # Creates the ProcCommandListener. def initialize(rights, block) super(rights) @block = block end + # Executes the block listening for the command. def execute(player, command) @block.call(player, command) end end -# A LoginListener that executes a Proc object with the player argument. -class ProcLoginListener - java_implements LoginListener - - def initialize(block) - super() - @block = block - end - - def execute(player) - @block.call(player) - end -end - # A LogoutListener that executes a Proc object with the player argument. -class ProcLogoutListener - java_implements LogoutListener +class ProcEventListener + java_implements EventListener + # Creates the ProcEventListener. def initialize(block) super() @block = block end - def execute(player) - @block.call(player) + # Executes the block handling the Event. + def handle(event, context) + @block.call(event, context) end end @@ -84,12 +76,14 @@ end # context, the player and the message. class ProcMessageHandler < MessageHandler + # Creates the ProcMessageListener. def initialize(block, option) - super() # required (with brackets!), see http://jira.codehaus.org/browse/JRUBY-679 + super() @block = block @option = option end + # Handles the message. def handle(ctx, player, message) @block.call(ctx, player, message) if (@option == 0 || @option == message.option) end @@ -99,11 +93,13 @@ end # A ScheduledTask which executes a Proc object with one argument (itself). class ProcScheduledTask < ScheduledTask + # Creates the ProcScheduledTask. def initialize(delay, immediate, block) super(delay, immediate) @block = block end + # Executes the block. def execute @block.call(self) end @@ -138,8 +134,7 @@ end # * :command # * :message # * :button -# * :login -# * :logout +# * Any valid Event, as a symbol in ruby snake_case form. # # A command takes one or two arguments (the command name and optionally the # minimum rights level to use it). The minimum rights level defaults to @@ -155,9 +150,10 @@ def on(type, *args, &block) when :command then on_command(args, block) when :message then on_message(args, block) when :button then on_button(args, block) - when :login then on_login(block) - when :logout then on_logout(block) - else raise 'Unknown message type.' + else + class_name = type.to_s.camelize.concat('Event') + type = Java::JavaClass.for_name("org.apollo.game.model.event.impl.#{class_name}") + $world.listen_for(type, ProcEventListener.new(block)) end end @@ -189,10 +185,9 @@ def on_message(args, proc) end end - if message.is_a?(Symbol) - class_name = message.to_s.camelize.concat('Message') - message = Java::JavaClass.for_name("org.apollo.game.message.impl.#{class_name}") - end + + class_name = message.to_s.camelize.concat('Message') + message = Java::JavaClass.for_name("org.apollo.game.message.impl.#{class_name}") $ctx.add_last_message_handler(message, ProcMessageHandler.new(proc, option)) end diff --git a/data/plugins/chat/private-messaging/friend.rb b/data/plugins/chat/private-messaging/friend.rb index dea9d769..ea4e0be3 100644 --- a/data/plugins/chat/private-messaging/friend.rb +++ b/data/plugins/chat/private-messaging/friend.rb @@ -42,7 +42,8 @@ on :message, :remove_friend do |ctx, player, message| end # Update the friend server status and send the friend/ignore lists of the player logging in. -on :login do |player| +on :login do |event, context| + player = event.player player.send(FriendServerStatusMessage.new(ServerStatus::CONNECTING)) player.send(IgnoreListMessage.new(player.ignored_usernames)) if player.ignored_usernames.size > 0 @@ -62,8 +63,8 @@ on :login do |player| end # Notifies the player's friends that the player has logged out. -on :logout do |player| - update_friends(player, 0) +on :logout do |event, context| + update_friends(event.player, 0) end diff --git a/data/plugins/skill/runecraft/tiara.rb b/data/plugins/skill/runecraft/tiara.rb index 8a77490d..9bcfe4f0 100644 --- a/data/plugins/skill/runecraft/tiara.rb +++ b/data/plugins/skill/runecraft/tiara.rb @@ -51,15 +51,13 @@ def append_tiara(hash) end # Sets the correct config upon login, if the player is wearing a tiara. -on :login do |player| +on :login do |event, context| + player = event.player hat = player.equipment.get(EquipmentConstants::HAT) - next if hat.nil? - - tiara = TIARAS_BY_ID[hat] - unless tiara.nil? - tiara.send_config - else - send_empty_config(player) + + unless hat.nil? + tiara = TIARAS_BY_ID[hat] + if tiara.nil? then send_empty_config(player) else tiara.send_config end end end @@ -67,7 +65,7 @@ end on :message, :second_object_action do |ctx, player, message| object_id = message.id tiara = TIARAS_BY_ALTAR[object_id] - return if tiara.nil? + next if tiara.nil? hat = player.equipment.get(EquipmentConstants::HAT) diff --git a/src/org/apollo/game/login/LoginDispatcher.java b/src/org/apollo/game/login/LoginDispatcher.java deleted file mode 100644 index 98968c27..00000000 --- a/src/org/apollo/game/login/LoginDispatcher.java +++ /dev/null @@ -1,38 +0,0 @@ -package org.apollo.game.login; - -import java.util.ArrayList; -import java.util.List; - -import org.apollo.game.model.entity.Player; - -/** - * A class that dispatches {@link Player}s to {@link LoginListener}s. - * - * @author Major - */ -public final class LoginDispatcher { - - /** - * A {@link List} of login listeners. - */ - private final List listeners = new ArrayList<>(); - - /** - * Dispatches a player to the appropriate login listener. - * - * @param player The player. - */ - public void dispatch(Player player) { - listeners.forEach(listener -> listener.execute(player)); - } - - /** - * Registers a listener with this dispatcher. - * - * @param listener The listener. - */ - public void register(LoginListener listener) { - listeners.add(listener); - } - -} \ No newline at end of file diff --git a/src/org/apollo/game/login/LoginListener.java b/src/org/apollo/game/login/LoginListener.java deleted file mode 100644 index 8530178d..00000000 --- a/src/org/apollo/game/login/LoginListener.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.apollo.game.login; - -import org.apollo.game.model.entity.Player; - -/** - * A class that should be extended for actions that should be executed when the player logs in. - * - * @author Major - */ -@FunctionalInterface -public interface LoginListener { - - /** - * Executes the action for this listener. - * - * @param player The player. - */ - public void execute(Player player); - -} \ No newline at end of file diff --git a/src/org/apollo/game/login/LogoutDispatcher.java b/src/org/apollo/game/login/LogoutDispatcher.java deleted file mode 100644 index cc3895eb..00000000 --- a/src/org/apollo/game/login/LogoutDispatcher.java +++ /dev/null @@ -1,38 +0,0 @@ -package org.apollo.game.login; - -import java.util.ArrayList; -import java.util.List; - -import org.apollo.game.model.entity.Player; - -/** - * A class that dispatches {@link Player}s to {@link LogoutListener}s. - * - * @author Major - */ -public final class LogoutDispatcher { - - /** - * A {@link List} of logout listeners. - */ - private final List listeners = new ArrayList<>(); - - /** - * Dispatches a player to the appropriate logout listener. - * - * @param player The player. - */ - public void dispatch(Player player) { - listeners.forEach(listener -> listener.execute(player)); - } - - /** - * Registers a listener with this dispatcher. - * - * @param listener The listener. - */ - public void register(LogoutListener listener) { - listeners.add(listener); - } - -} diff --git a/src/org/apollo/game/login/LogoutListener.java b/src/org/apollo/game/login/LogoutListener.java deleted file mode 100644 index 65aa0dfb..00000000 --- a/src/org/apollo/game/login/LogoutListener.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.apollo.game.login; - -import org.apollo.game.model.entity.Player; - -/** - * An interface that should be implemented for actions that should be executed when the player logs out. - * - * @author Major - */ -@FunctionalInterface -public interface LogoutListener { - - /** - * Executes the action for this listener. - * - * @param player The player. - */ - public void execute(Player player); - -} \ No newline at end of file diff --git a/src/org/apollo/game/login/package-info.java b/src/org/apollo/game/login/package-info.java deleted file mode 100644 index b157b152..00000000 --- a/src/org/apollo/game/login/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * Contains login and logout listeners. - */ -package org.apollo.game.login; \ No newline at end of file diff --git a/src/org/apollo/game/model/World.java b/src/org/apollo/game/model/World.java index c1cf8898..29bd4e36 100644 --- a/src/org/apollo/game/model/World.java +++ b/src/org/apollo/game/model/World.java @@ -15,8 +15,6 @@ import org.apollo.fs.decoder.ItemDefinitionDecoder; import org.apollo.fs.decoder.NpcDefinitionDecoder; import org.apollo.fs.decoder.ObjectDefinitionDecoder; import org.apollo.game.command.CommandDispatcher; -import org.apollo.game.login.LoginDispatcher; -import org.apollo.game.login.LogoutDispatcher; import org.apollo.game.model.area.Sector; import org.apollo.game.model.area.SectorRepository; import org.apollo.game.model.def.EquipmentDefinition; @@ -27,9 +25,9 @@ import org.apollo.game.model.entity.Entity; import org.apollo.game.model.entity.GameObject; import org.apollo.game.model.entity.Npc; import org.apollo.game.model.entity.Player; -import org.apollo.game.model.entity.event.Event; -import org.apollo.game.model.entity.event.EventListener; -import org.apollo.game.model.entity.event.EventListenerChainSet; +import org.apollo.game.model.event.Event; +import org.apollo.game.model.event.EventListener; +import org.apollo.game.model.event.EventListenerChainSet; import org.apollo.game.scheduling.ScheduledTask; import org.apollo.game.scheduling.Scheduler; import org.apollo.io.EquipmentDefinitionParser; @@ -99,16 +97,6 @@ public final class World { */ private final EventListenerChainSet events = new EventListenerChainSet(); - /** - * The login dispatcher. - */ - private final LoginDispatcher loginDispatcher = new LoginDispatcher(); - - /** - * The logout dispatcher. - */ - private final LogoutDispatcher logoutDispatcher = new LogoutDispatcher(); - /** * The {@link MobRepository} of {@link Npc}s. */ @@ -160,24 +148,6 @@ public final class World { return commandDispatcher; } - /** - * Gets the {@link LoginDispatcher}. - * - * @return The dispatcher. - */ - public LoginDispatcher getLoginDispatcher() { - return loginDispatcher; - } - - /** - * Gets the {@link LogoutDispatcher}. - * - * @return The dispatcher. - */ - public LogoutDispatcher getLogoutDispatcher() { - return logoutDispatcher; - } - /** * Gets the npc repository. * @@ -394,8 +364,6 @@ public final class World { Sector sector = sectors.fromPosition(player.getPosition()); sector.removeEntity(player); - - logoutDispatcher.dispatch(player); } else { logger.warning("Could not find player " + player + " to unregister!"); } diff --git a/src/org/apollo/game/model/entity/Player.java b/src/org/apollo/game/model/entity/Player.java index 9b61cfa6..0004434d 100644 --- a/src/org/apollo/game/model/entity/Player.java +++ b/src/org/apollo/game/model/entity/Player.java @@ -19,6 +19,7 @@ import org.apollo.game.model.Appearance; import org.apollo.game.model.Position; import org.apollo.game.model.World; import org.apollo.game.model.area.Sector; +import org.apollo.game.model.event.impl.LoginEvent; import org.apollo.game.model.inter.InterfaceConstants; import org.apollo.game.model.inter.InterfaceListener; import org.apollo.game.model.inter.InterfaceSet; @@ -701,7 +702,7 @@ public final class Player extends Mob { bank.forceRefresh(); skillSet.forceRefresh(); - World.getWorld().getLoginDispatcher().dispatch(this); + World.getWorld().submit(new LoginEvent(this)); } /** diff --git a/src/org/apollo/game/model/entity/event/Event.java b/src/org/apollo/game/model/event/Event.java similarity index 72% rename from src/org/apollo/game/model/entity/event/Event.java rename to src/org/apollo/game/model/event/Event.java index cf349844..90d9e5b9 100644 --- a/src/org/apollo/game/model/entity/event/Event.java +++ b/src/org/apollo/game/model/event/Event.java @@ -1,4 +1,4 @@ -package org.apollo.game.model.entity.event; +package org.apollo.game.model.event; /** * A type of event that may occur in the game world. diff --git a/src/org/apollo/game/model/entity/event/EventContext.java b/src/org/apollo/game/model/event/EventContext.java similarity index 87% rename from src/org/apollo/game/model/entity/event/EventContext.java rename to src/org/apollo/game/model/event/EventContext.java index f9568779..ad07c72c 100644 --- a/src/org/apollo/game/model/entity/event/EventContext.java +++ b/src/org/apollo/game/model/event/EventContext.java @@ -1,4 +1,4 @@ -package org.apollo.game.model.entity.event; +package org.apollo.game.model.event; /** * The context of an {@link Event}. @@ -15,7 +15,7 @@ final class EventContext { /** * Terminates the Event chain. */ - public void terminate() { + public void terminateEvent() { terminated = true; } diff --git a/src/org/apollo/game/model/entity/event/EventListener.java b/src/org/apollo/game/model/event/EventListener.java similarity index 89% rename from src/org/apollo/game/model/entity/event/EventListener.java rename to src/org/apollo/game/model/event/EventListener.java index 46ad7a1c..8a4392a7 100644 --- a/src/org/apollo/game/model/entity/event/EventListener.java +++ b/src/org/apollo/game/model/event/EventListener.java @@ -1,4 +1,4 @@ -package org.apollo.game.model.entity.event; +package org.apollo.game.model.event; /** * A listener for an {@link Event} that may occur in the game world. diff --git a/src/org/apollo/game/model/entity/event/EventListenerChain.java b/src/org/apollo/game/model/event/EventListenerChain.java similarity index 97% rename from src/org/apollo/game/model/entity/event/EventListenerChain.java rename to src/org/apollo/game/model/event/EventListenerChain.java index b46f8dc9..724dbae9 100644 --- a/src/org/apollo/game/model/entity/event/EventListenerChain.java +++ b/src/org/apollo/game/model/event/EventListenerChain.java @@ -1,4 +1,4 @@ -package org.apollo.game.model.entity.event; +package org.apollo.game.model.event; import java.util.ArrayList; import java.util.List; diff --git a/src/org/apollo/game/model/entity/event/EventListenerChainSet.java b/src/org/apollo/game/model/event/EventListenerChainSet.java similarity index 91% rename from src/org/apollo/game/model/entity/event/EventListenerChainSet.java rename to src/org/apollo/game/model/event/EventListenerChainSet.java index 4df75722..8dbe8bfa 100644 --- a/src/org/apollo/game/model/entity/event/EventListenerChainSet.java +++ b/src/org/apollo/game/model/event/EventListenerChainSet.java @@ -1,4 +1,4 @@ -package org.apollo.game.model.entity.event; +package org.apollo.game.model.event; import java.util.HashMap; import java.util.Map; @@ -23,8 +23,8 @@ public final class EventListenerChainSet { */ public boolean notify(E event) { @SuppressWarnings("unchecked") - EventListenerChain chain = (EventListenerChain) chains.get(event); - return chain.notify(event); + EventListenerChain chain = (EventListenerChain) chains.get(event.getClass()); + return (chain == null) ? true : chain.notify(event); } /** diff --git a/src/org/apollo/game/model/event/PlayerEvent.java b/src/org/apollo/game/model/event/PlayerEvent.java new file mode 100644 index 00000000..23272210 --- /dev/null +++ b/src/org/apollo/game/model/event/PlayerEvent.java @@ -0,0 +1,35 @@ +package org.apollo.game.model.event; + +import org.apollo.game.model.entity.Player; + +/** + * An {@link Event} involving a {@link Player}. + * + * @author Major + */ +public abstract class PlayerEvent extends Event { + + /** + * The Player. + */ + private final Player player; + + /** + * Creates the PlayerEvent. + * + * @param player The {@link Player}. + */ + public PlayerEvent(Player player) { + this.player = player; + } + + /** + * Gets the {@link Player}. + * + * @return The Player. + */ + public Player getPlayer() { + return player; + } + +} \ No newline at end of file diff --git a/src/org/apollo/game/model/event/impl/CloseInterfacesEvent.java b/src/org/apollo/game/model/event/impl/CloseInterfacesEvent.java new file mode 100644 index 00000000..c2f08c74 --- /dev/null +++ b/src/org/apollo/game/model/event/impl/CloseInterfacesEvent.java @@ -0,0 +1,23 @@ +package org.apollo.game.model.event.impl; + +import org.apollo.game.model.entity.Player; +import org.apollo.game.model.event.Event; +import org.apollo.game.model.event.PlayerEvent; + +/** + * An {@link Event} indicating that a player's open interfaces are about to be closed. + * + * @author Major + */ +public final class CloseInterfacesEvent extends PlayerEvent { + + /** + * Creates the CloseInterfacesEvent. + * + * @param player The {@link Player} whose interfaces are being closed. + */ + public CloseInterfacesEvent(Player player) { + super(player); + } + +} \ No newline at end of file diff --git a/src/org/apollo/game/model/event/impl/LoginEvent.java b/src/org/apollo/game/model/event/impl/LoginEvent.java new file mode 100644 index 00000000..307764f4 --- /dev/null +++ b/src/org/apollo/game/model/event/impl/LoginEvent.java @@ -0,0 +1,22 @@ +package org.apollo.game.model.event.impl; + +import org.apollo.game.model.entity.Player; +import org.apollo.game.model.event.PlayerEvent; + +/** + * A {@link PlayerEvent} that is fired when a {@link Player} logs in. + * + * @author Major + */ +public final class LoginEvent extends PlayerEvent { + + /** + * Creates the LoginEvent. + * + * @param player The {@link Player} logging in. + */ + public LoginEvent(Player player) { + super(player); + } + +} \ No newline at end of file diff --git a/src/org/apollo/game/model/event/impl/LogoutEvent.java b/src/org/apollo/game/model/event/impl/LogoutEvent.java new file mode 100644 index 00000000..16f17390 --- /dev/null +++ b/src/org/apollo/game/model/event/impl/LogoutEvent.java @@ -0,0 +1,22 @@ +package org.apollo.game.model.event.impl; + +import org.apollo.game.model.entity.Player; +import org.apollo.game.model.event.PlayerEvent; + +/** + * A {@link PlayerEvent} that is fired when a {@link Player} logs out. + * + * @author Major + */ +public final class LogoutEvent extends PlayerEvent { + + /** + * Creates the LogoutEvent. + * + * @param player The {@link Player} logging out. + */ + public LogoutEvent(Player player) { + super(player); + } + +} \ No newline at end of file diff --git a/src/org/apollo/game/model/event/impl/package-info.java b/src/org/apollo/game/model/event/impl/package-info.java new file mode 100644 index 00000000..a6527103 --- /dev/null +++ b/src/org/apollo/game/model/event/impl/package-info.java @@ -0,0 +1,4 @@ +/** + * Contains Event implementations. + */ +package org.apollo.game.model.event.impl; \ No newline at end of file diff --git a/src/org/apollo/game/model/entity/event/package-info.java b/src/org/apollo/game/model/event/package-info.java similarity index 50% rename from src/org/apollo/game/model/entity/event/package-info.java rename to src/org/apollo/game/model/event/package-info.java index 6b10ac54..8167081f 100644 --- a/src/org/apollo/game/model/entity/event/package-info.java +++ b/src/org/apollo/game/model/event/package-info.java @@ -1,4 +1,4 @@ /** * Contains event-related classes. */ -package org.apollo.game.model.entity.event; \ No newline at end of file +package org.apollo.game.model.event; \ No newline at end of file diff --git a/src/org/apollo/game/model/inter/InterfaceSet.java b/src/org/apollo/game/model/inter/InterfaceSet.java index 6b9dfeec..5743a956 100644 --- a/src/org/apollo/game/model/inter/InterfaceSet.java +++ b/src/org/apollo/game/model/inter/InterfaceSet.java @@ -11,7 +11,9 @@ import org.apollo.game.message.impl.OpenInterfaceMessage; import org.apollo.game.message.impl.OpenInterfaceSidebarMessage; import org.apollo.game.message.impl.OpenOverlayMessage; import org.apollo.game.message.impl.OpenSidebarMessage; +import org.apollo.game.model.World; import org.apollo.game.model.entity.Player; +import org.apollo.game.model.event.impl.CloseInterfacesEvent; import org.apollo.game.model.inter.dialogue.DialogueListener; import org.apollo.game.model.inv.InventoryListener; @@ -86,8 +88,11 @@ public final class InterfaceSet { * Closes the current open interface(s). */ public void close() { - closeAndNotify(); - player.send(new CloseInterfaceMessage()); + CloseInterfacesEvent event = new CloseInterfacesEvent(player); + if (World.getWorld().submit(event)) { + closeAndNotify(); + player.send(new CloseInterfaceMessage()); + } } /** diff --git a/src/org/apollo/util/plugin/PluginContext.java b/src/org/apollo/util/plugin/PluginContext.java index 8d88f9f1..a33fe386 100644 --- a/src/org/apollo/util/plugin/PluginContext.java +++ b/src/org/apollo/util/plugin/PluginContext.java @@ -3,24 +3,24 @@ package org.apollo.util.plugin; import org.apollo.ServerContext; import org.apollo.game.GameService; import org.apollo.game.command.CommandListener; -import org.apollo.game.login.LoginListener; -import org.apollo.game.login.LogoutListener; import org.apollo.game.message.Message; import org.apollo.game.message.handler.MessageHandler; import org.apollo.game.message.handler.MessageHandlerChain; import org.apollo.game.message.handler.MessageHandlerChainGroup; import org.apollo.game.model.World; +import org.apollo.game.model.event.EventListener; +import org.apollo.game.model.event.impl.LoginEvent; +import org.apollo.game.model.event.impl.LogoutEvent; /** * The {@link PluginContext} contains methods a plugin can use to interface with the server, for example, by adding * {@link MessageHandler}s to {@link MessageHandlerChain}s. * * @author Graham + * @author Major */ public final class PluginContext { - // TODO move listeners to world? - /** * Adds a {@link CommandListener}. * @@ -32,21 +32,21 @@ public final class PluginContext { } /** - * Adds a {@link LoginListener}. + * Adds an {@link EventListener} for a {@link LoginEvent}. * * @param listener The listener. */ - public static void addLoginListener(LoginListener listener) { - World.getWorld().getLoginDispatcher().register(listener); + public static void addLoginListener(EventListener listener) { + World.getWorld().listenFor(LoginEvent.class, listener); } /** - * Adds a {@link LogoutListener}. + * Adds an {@link EventListener} for a {@link LogoutEvent}. * * @param listener The listener. */ - public static void addLogoutListener(LogoutListener listener) { - World.getWorld().getLogoutDispatcher().register(listener); + public static void addLogoutListener(EventListener listener) { + World.getWorld().listenFor(LogoutEvent.class, listener); } /** From d81f0feaf73b23971497e6aa2c940938815991c2 Mon Sep 17 00:00:00 2001 From: Major- Date: Fri, 27 Feb 2015 04:34:09 +0000 Subject: [PATCH 24/59] Move EventContext functionality into Event, remove EventContext, add LogoutEvent support. --- data/plugins/bootstrap.rb | 7 +++-- data/plugins/chat/private-messaging/friend.rb | 7 ++--- data/plugins/skill/runecraft/tiara.rb | 4 +-- src/org/apollo/game/model/entity/Player.java | 5 ++- src/org/apollo/game/model/event/Event.java | 21 +++++++++++++ .../apollo/game/model/event/EventContext.java | 31 ------------------- .../game/model/event/EventListener.java | 3 +- .../game/model/event/EventListenerChain.java | 7 ++--- 8 files changed, 39 insertions(+), 46 deletions(-) delete mode 100644 src/org/apollo/game/model/event/EventContext.java diff --git a/data/plugins/bootstrap.rb b/data/plugins/bootstrap.rb index 9f90a4c5..6d759fa2 100644 --- a/data/plugins/bootstrap.rb +++ b/data/plugins/bootstrap.rb @@ -19,6 +19,7 @@ java_import 'org.apollo.game.message.handler.MessageHandler' java_import 'org.apollo.game.model.World' java_import 'org.apollo.game.model.entity.Player' java_import 'org.apollo.game.model.event.EventListener' +java_import 'org.apollo.game.model.event.PlayerEvent' java_import 'org.apollo.game.model.setting.PrivilegeLevel' java_import 'org.apollo.game.scheduling.ScheduledTask' java_import 'org.apollo.util.plugin.PluginContext' @@ -66,8 +67,10 @@ class ProcEventListener end # Executes the block handling the Event. - def handle(event, context) - @block.call(event, context) + def handle(event) + args = [ event ] + args << event.player if event.kind_of?(PlayerEvent) + @block.call(*args) end end diff --git a/data/plugins/chat/private-messaging/friend.rb b/data/plugins/chat/private-messaging/friend.rb index ea4e0be3..6d1085e6 100644 --- a/data/plugins/chat/private-messaging/friend.rb +++ b/data/plugins/chat/private-messaging/friend.rb @@ -42,8 +42,7 @@ on :message, :remove_friend do |ctx, player, message| end # Update the friend server status and send the friend/ignore lists of the player logging in. -on :login do |event, context| - player = event.player +on :login do |event, player| player.send(FriendServerStatusMessage.new(ServerStatus::CONNECTING)) player.send(IgnoreListMessage.new(player.ignored_usernames)) if player.ignored_usernames.size > 0 @@ -63,8 +62,8 @@ on :login do |event, context| end # Notifies the player's friends that the player has logged out. -on :logout do |event, context| - update_friends(event.player, 0) +on :logout do |event, player| + update_friends(player, 0) end diff --git a/data/plugins/skill/runecraft/tiara.rb b/data/plugins/skill/runecraft/tiara.rb index 9bcfe4f0..9e1559f9 100644 --- a/data/plugins/skill/runecraft/tiara.rb +++ b/data/plugins/skill/runecraft/tiara.rb @@ -44,14 +44,14 @@ end # Appends a tiara to the list. def append_tiara(hash) - raise 'Hash must contain a tiara id, altar id, talisman id, a bitshift number, and experience.' unless hash.has_key?(:tiara_id) && hash.has_key?(:altar) && hash.has_key?(:talisman) && hash.has_key?(:bitshift) && hash.has_key?(:experience) + raise 'Hash must contain a tiara id, altar id, talisman id, a bitshift number, and experience.' unless hash.has_keys?(:altar, :bitshift, :experience, :talisman, :tiara_id) tiara_id = hash[:tiara_id]; altar = hash[:altar]; talisman = hash[:talisman]; bitshift = hash[:bitshift]; experience = hash[:experience] TIARAS_BY_TALISMAN[talisman] = TIARAS_BY_ID[tiara_id] = TIARAS_BY_ALTAR[altar] = Tiara.new(tiara_id, altar, talisman, bitshift, experience) end # Sets the correct config upon login, if the player is wearing a tiara. -on :login do |event, context| +on :login do |event, player| player = event.player hat = player.equipment.get(EquipmentConstants::HAT) diff --git a/src/org/apollo/game/model/entity/Player.java b/src/org/apollo/game/model/entity/Player.java index 0004434d..578dfecd 100644 --- a/src/org/apollo/game/model/entity/Player.java +++ b/src/org/apollo/game/model/entity/Player.java @@ -20,6 +20,7 @@ import org.apollo.game.model.Position; import org.apollo.game.model.World; import org.apollo.game.model.area.Sector; import org.apollo.game.model.event.impl.LoginEvent; +import org.apollo.game.model.event.impl.LogoutEvent; import org.apollo.game.model.inter.InterfaceConstants; import org.apollo.game.model.inter.InterfaceListener; import org.apollo.game.model.inter.InterfaceSet; @@ -600,7 +601,9 @@ public final class Player extends Mob { * Logs the player out, if possible. */ public void logout() { - send(new LogoutMessage()); + if (World.getWorld().submit(new LogoutEvent(this))) { + send(new LogoutMessage()); + } } /** diff --git a/src/org/apollo/game/model/event/Event.java b/src/org/apollo/game/model/event/Event.java index 90d9e5b9..8d71d84e 100644 --- a/src/org/apollo/game/model/event/Event.java +++ b/src/org/apollo/game/model/event/Event.java @@ -6,5 +6,26 @@ package org.apollo.game.model.event; * @author Major */ public abstract class Event { + + /** + * Indicates whether or not the Event chain has been terminated. + */ + private boolean terminated; + /** + * Terminates the Event chain. + */ + public final void terminate() { + terminated = true; + } + + /** + * Returns whether or not the Event chain has been terminated. + * + * @return {@code true} if the Event chain has been terminated, otherwise {@code false}. + */ + public final boolean terminated() { + return terminated; + } + } \ No newline at end of file diff --git a/src/org/apollo/game/model/event/EventContext.java b/src/org/apollo/game/model/event/EventContext.java deleted file mode 100644 index ad07c72c..00000000 --- a/src/org/apollo/game/model/event/EventContext.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.apollo.game.model.event; - -/** - * The context of an {@link Event}. - * - * @author Major - */ -final class EventContext { - - /** - * Indicates whether or not the Event chain has been terminated. - */ - private boolean terminated; - - /** - * Terminates the Event chain. - */ - public void terminateEvent() { - terminated = true; - } - - /** - * Returns whether or not the Event chain has been terminated. - * - * @return {@code true} if the Event chain has been terminated, otherwise {@code false}. - */ - public boolean terminated() { - return terminated; - } - -} \ No newline at end of file diff --git a/src/org/apollo/game/model/event/EventListener.java b/src/org/apollo/game/model/event/EventListener.java index 8a4392a7..7a5306b8 100644 --- a/src/org/apollo/game/model/event/EventListener.java +++ b/src/org/apollo/game/model/event/EventListener.java @@ -14,8 +14,7 @@ public interface EventListener { * Handles the {@link Event} that occurred. * * @param event The Event. - * @param context The {@link EventContext}. */ - public void handle(E event, EventContext context); + public void handle(E event); } \ No newline at end of file diff --git a/src/org/apollo/game/model/event/EventListenerChain.java b/src/org/apollo/game/model/event/EventListenerChain.java index 724dbae9..a2fbca2d 100644 --- a/src/org/apollo/game/model/event/EventListenerChain.java +++ b/src/org/apollo/game/model/event/EventListenerChain.java @@ -48,16 +48,15 @@ final class EventListenerChain { * @return {@code true} if the Event should continue on with its outcome, {@code false} if not. */ public boolean notify(E event) { - EventContext context = new EventContext(); for (EventListener listener : listeners) { - listener.handle(event, context); + listener.handle(event); - if (context.terminated()) { + if (event.terminated()) { return false; } } - return false; + return true; } @Override From 4cf2af762d04a604515915ef294f0cbf694776bf Mon Sep 17 00:00:00 2001 From: Major- Date: Fri, 27 Feb 2015 05:55:35 +0000 Subject: [PATCH 25/59] Remove debug message from attributes.rb. --- data/plugins/entity/attributes/attributes.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/data/plugins/entity/attributes/attributes.rb b/data/plugins/entity/attributes/attributes.rb index 161ac917..42261756 100644 --- a/data/plugins/entity/attributes/attributes.rb +++ b/data/plugins/entity/attributes/attributes.rb @@ -19,7 +19,6 @@ class Entity if name[-1] == "=" raise "Expected argument count of 1, received #{args.length}" unless args.length == 1 - puts name name = name[0...-1].strip # Drop the equals set_attribute(name, to_attribute(args[0])) elsif AttributeMap::get_definition(name) == nil From 7648abcd8f2001cc8547036b45b549b8e36f7be6 Mon Sep 17 00:00:00 2001 From: Major- Date: Fri, 27 Feb 2015 05:56:09 +0000 Subject: [PATCH 26/59] Add FlashingTabClickedMessage. --- .../impl/FlashingTabClickedMessage.java | 35 +++++++++++++++++++ .../FlashingTabClickedMessageDecoder.java | 23 ++++++++++++ .../apollo/net/release/r317/Release317.java | 1 + .../FlashingTabClickedMessageDecoder.java | 23 ++++++++++++ .../apollo/net/release/r377/Release377.java | 1 + 5 files changed, 83 insertions(+) create mode 100644 src/org/apollo/game/message/impl/FlashingTabClickedMessage.java create mode 100644 src/org/apollo/net/release/r317/FlashingTabClickedMessageDecoder.java create mode 100644 src/org/apollo/net/release/r377/FlashingTabClickedMessageDecoder.java diff --git a/src/org/apollo/game/message/impl/FlashingTabClickedMessage.java b/src/org/apollo/game/message/impl/FlashingTabClickedMessage.java new file mode 100644 index 00000000..ae7e1056 --- /dev/null +++ b/src/org/apollo/game/message/impl/FlashingTabClickedMessage.java @@ -0,0 +1,35 @@ +package org.apollo.game.message.impl; + +import org.apollo.game.message.Message; + +/** + * A {@link Message} sent by the client indicating a flashing tab has been clicked. + * + * @author Major + */ +public final class FlashingTabClickedMessage extends Message { + + /** + * The tab that was clicked. + */ + private final int tab; + + /** + * Creates the FlashingTabClickedMessage. + * + * @param tab The tab that was clicked. + */ + public FlashingTabClickedMessage(int tab) { + this.tab = tab; + } + + /** + * Gets the index of the tab that was clicked. + * + * @return The tab index. + */ + public int getTab() { + return tab; + } + +} \ No newline at end of file diff --git a/src/org/apollo/net/release/r317/FlashingTabClickedMessageDecoder.java b/src/org/apollo/net/release/r317/FlashingTabClickedMessageDecoder.java new file mode 100644 index 00000000..780be27c --- /dev/null +++ b/src/org/apollo/net/release/r317/FlashingTabClickedMessageDecoder.java @@ -0,0 +1,23 @@ +package org.apollo.net.release.r317; + +import org.apollo.game.message.impl.FlashingTabClickedMessage; +import org.apollo.net.codec.game.DataType; +import org.apollo.net.codec.game.GamePacket; +import org.apollo.net.codec.game.GamePacketReader; +import org.apollo.net.release.MessageDecoder; + +/** + * A {@link MessageDecoder} for the {@link FlashingTabClickedMessage}. + * + * @author Major + */ +public final class FlashingTabClickedMessageDecoder extends MessageDecoder { + + @Override + public FlashingTabClickedMessage decode(GamePacket packet) { + GamePacketReader reader = new GamePacketReader(packet); + int tab = (int) reader.getUnsigned(DataType.BYTE); + return new FlashingTabClickedMessage(tab); + } + +} \ No newline at end of file diff --git a/src/org/apollo/net/release/r317/Release317.java b/src/org/apollo/net/release/r317/Release317.java index 0f4d3cc0..78a0489f 100644 --- a/src/org/apollo/net/release/r317/Release317.java +++ b/src/org/apollo/net/release/r317/Release317.java @@ -127,6 +127,7 @@ public final class Release317 extends Release { register(130, new ClosedInterfaceMessageDecoder()); register(208, new EnteredAmountMessageDecoder()); register(40, new DialogueContinueMessageDecoder()); + register(120, new FlashingTabClickedMessageDecoder()); register(53, new ItemOnItemMessageDecoder()); register(237, new MagicOnItemMessageDecoder()); diff --git a/src/org/apollo/net/release/r377/FlashingTabClickedMessageDecoder.java b/src/org/apollo/net/release/r377/FlashingTabClickedMessageDecoder.java new file mode 100644 index 00000000..7d97ea93 --- /dev/null +++ b/src/org/apollo/net/release/r377/FlashingTabClickedMessageDecoder.java @@ -0,0 +1,23 @@ +package org.apollo.net.release.r377; + +import org.apollo.game.message.impl.FlashingTabClickedMessage; +import org.apollo.net.codec.game.DataType; +import org.apollo.net.codec.game.GamePacket; +import org.apollo.net.codec.game.GamePacketReader; +import org.apollo.net.release.MessageDecoder; + +/** + * A {@link MessageDecoder} for the {@link FlashingTabClickedMessage}. + * + * @author Major + */ +public final class FlashingTabClickedMessageDecoder extends MessageDecoder { + + @Override + public FlashingTabClickedMessage decode(GamePacket packet) { + GamePacketReader reader = new GamePacketReader(packet); + int tab = (int) reader.getUnsigned(DataType.BYTE); + return new FlashingTabClickedMessage(tab); + } + +} \ No newline at end of file diff --git a/src/org/apollo/net/release/r377/Release377.java b/src/org/apollo/net/release/r377/Release377.java index db4868e7..4903d61d 100644 --- a/src/org/apollo/net/release/r377/Release377.java +++ b/src/org/apollo/net/release/r377/Release377.java @@ -127,6 +127,7 @@ public final class Release377 extends Release { register(110, new ClosedInterfaceMessageDecoder()); register(75, new EnteredAmountMessageDecoder()); register(226, new DialogueContinueMessageDecoder()); + register(119, new FlashingTabClickedMessageDecoder()); register(1, new ItemOnItemMessageDecoder()); register(36, new MagicOnItemMessageDecoder()); From 7f7656112d07007bcb6958814723d7328ac91152 Mon Sep 17 00:00:00 2001 From: Major- Date: Fri, 27 Feb 2015 17:45:03 +0000 Subject: [PATCH 27/59] Rename 'OpenDialogueOverlayInterfaceMessage' to 'OpenDialogueOverlayMessage'. --- .../game/message/impl/HintIconMessage.java | 20 ++++++++++- .../impl/OpenDialogueOverlayMessage.java | 35 ++++++++++++++++++ .../apollo/game/model/inter/InterfaceSet.java | 36 ++++++++++++++++--- .../OpenDialogueOverlayMessageEncoder.java | 25 +++++++++++++ .../apollo/net/release/r317/Release317.java | 3 ++ .../OpenDialogueOverlayMessageEncoder.java | 24 +++++++++++++ .../apollo/net/release/r377/Release377.java | 2 ++ 7 files changed, 139 insertions(+), 6 deletions(-) create mode 100644 src/org/apollo/game/message/impl/OpenDialogueOverlayMessage.java create mode 100644 src/org/apollo/net/release/r317/OpenDialogueOverlayMessageEncoder.java create mode 100644 src/org/apollo/net/release/r377/OpenDialogueOverlayMessageEncoder.java diff --git a/src/org/apollo/game/message/impl/HintIconMessage.java b/src/org/apollo/game/message/impl/HintIconMessage.java index cbd2167b..6a9757ac 100644 --- a/src/org/apollo/game/message/impl/HintIconMessage.java +++ b/src/org/apollo/game/message/impl/HintIconMessage.java @@ -13,7 +13,7 @@ import org.apollo.game.model.Position; */ public final class HintIconMessage extends Message { - // TODO identify the other types and use an enum. + // TODO identify the other types. /** * The type of a HintIcon. @@ -75,6 +75,24 @@ public final class HintIconMessage extends Message { return new HintIconMessage(Type.PLAYER, Optional.of(index), Optional.empty()); } + /** + * Creates a HintIconMessage that removes the current Npc hint icon. + * + * @return The HintIconMessage. + */ + public static HintIconMessage resetNpc() { + return forNpc(-1); + } + + /** + * Creates a HintIconMessage that removes the current Player hint icon. + * + * @return The HintIconMessage. + */ + public static HintIconMessage resetPlayer() { + return forPlayer(-1); + } + /** * The index of the Mob, if applicable. */ diff --git a/src/org/apollo/game/message/impl/OpenDialogueOverlayMessage.java b/src/org/apollo/game/message/impl/OpenDialogueOverlayMessage.java new file mode 100644 index 00000000..b785f569 --- /dev/null +++ b/src/org/apollo/game/message/impl/OpenDialogueOverlayMessage.java @@ -0,0 +1,35 @@ +package org.apollo.game.message.impl; + +import org.apollo.game.message.Message; + +/** + * A {@link Message} sent to the client that opens a dialogue interface (an interface that appears in the chat box). + * + * @author Chris Fletcher + */ +public final class OpenDialogueOverlayMessage extends Message { + + /** + * The interface id. + */ + private final int interfaceId; + + /** + * Creates a new message with the specified interface id. + * + * @param interfaceId The interface id. + */ + public OpenDialogueOverlayMessage(int interfaceId) { + this.interfaceId = interfaceId; + } + + /** + * Gets the interface id. + * + * @return The interface id. + */ + public int getInterfaceId() { + return interfaceId; + } + +} \ No newline at end of file diff --git a/src/org/apollo/game/model/inter/InterfaceSet.java b/src/org/apollo/game/model/inter/InterfaceSet.java index 5743a956..3e77387e 100644 --- a/src/org/apollo/game/model/inter/InterfaceSet.java +++ b/src/org/apollo/game/model/inter/InterfaceSet.java @@ -7,6 +7,7 @@ import java.util.Optional; import org.apollo.game.message.impl.CloseInterfaceMessage; import org.apollo.game.message.impl.EnterAmountMessage; import org.apollo.game.message.impl.OpenDialogueInterfaceMessage; +import org.apollo.game.message.impl.OpenDialogueOverlayMessage; import org.apollo.game.message.impl.OpenInterfaceMessage; import org.apollo.game.message.impl.OpenInterfaceSidebarMessage; import org.apollo.game.message.impl.OpenOverlayMessage; @@ -144,10 +145,10 @@ public final class InterfaceSet { } /** - * Opens a chat box dialogue. + * Opens a dialogue interface. * - * @param listener The listener for the dialogue. - * @param dialogueId The dialogue's id. + * @param listener The {@link DialogueListener}. + * @param dialogueId The dialogue id. */ public void openDialogue(DialogueListener listener, int dialogueId) { closeAndNotify(); @@ -160,14 +161,39 @@ public final class InterfaceSet { } /** - * Opens a chat box dialogue. + * Opens a dialogue. * - * @param dialogueId The dialogue's id. + * @param dialogueId The dialogue id. */ public void openDialogue(int dialogueId) { openDialogue(null, dialogueId); } + /** + * Opens a dialogue overlay interface. + * + * @param listener The {@link DialogueListener}. + * @param dialogueId The dialogue id. + */ + public void openDialogueOverlay(DialogueListener listener, int dialogueId) { + closeAndNotify(); + + this.dialogueListener = Optional.ofNullable(listener); + this.listener = Optional.ofNullable(listener); + + interfaces.put(InterfaceType.DIALOGUE, dialogueId); + player.send(new OpenDialogueOverlayMessage(dialogueId)); + } + + /** + * Opens a dialogue overlay. + * + * @param dialogueId The dialogue id. + */ + public void openDialogueOverlay(int dialogueId) { + openDialogueOverlay(null, dialogueId); + } + /** * Opens the enter amount dialogue. * diff --git a/src/org/apollo/net/release/r317/OpenDialogueOverlayMessageEncoder.java b/src/org/apollo/net/release/r317/OpenDialogueOverlayMessageEncoder.java new file mode 100644 index 00000000..a53afa78 --- /dev/null +++ b/src/org/apollo/net/release/r317/OpenDialogueOverlayMessageEncoder.java @@ -0,0 +1,25 @@ +package org.apollo.net.release.r317; + +import org.apollo.game.message.impl.OpenDialogueOverlayMessage; +import org.apollo.net.codec.game.DataOrder; +import org.apollo.net.codec.game.DataTransformation; +import org.apollo.net.codec.game.DataType; +import org.apollo.net.codec.game.GamePacket; +import org.apollo.net.codec.game.GamePacketBuilder; +import org.apollo.net.release.MessageEncoder; + +/** + * A {@link MessageEncoder} for the {@link OpenDialogueOverlayMessage}. + * + * @author Major + */ +public final class OpenDialogueOverlayMessageEncoder extends MessageEncoder { + + @Override + public GamePacket encode(OpenDialogueOverlayMessage message) { + GamePacketBuilder builder = new GamePacketBuilder(218); + builder.put(DataType.SHORT, DataOrder.LITTLE, DataTransformation.ADD, message.getInterfaceId()); + return builder.toGamePacket(); + } + +} \ No newline at end of file diff --git a/src/org/apollo/net/release/r317/Release317.java b/src/org/apollo/net/release/r317/Release317.java index 78a0489f..39c77ab4 100644 --- a/src/org/apollo/net/release/r317/Release317.java +++ b/src/org/apollo/net/release/r317/Release317.java @@ -16,6 +16,7 @@ import org.apollo.game.message.impl.IgnoreListMessage; import org.apollo.game.message.impl.LogoutMessage; import org.apollo.game.message.impl.NpcSynchronizationMessage; import org.apollo.game.message.impl.OpenDialogueInterfaceMessage; +import org.apollo.game.message.impl.OpenDialogueOverlayMessage; import org.apollo.game.message.impl.OpenInterfaceMessage; import org.apollo.game.message.impl.OpenInterfaceSidebarMessage; import org.apollo.game.message.impl.OpenOverlayMessage; @@ -214,5 +215,7 @@ public final class Release317 extends Release { register(FlashTabInterfaceMessage.class, new FlashTabInterfaceMessageEncoder()); register(OpenSidebarMessage.class, new OpenSidebarMessageEncoder()); register(OpenOverlayMessage.class, new OpenOverlayMessageEncoder()); + register(OpenDialogueOverlayMessage.class, new OpenDialogueOverlayMessageEncoder()); } + } \ No newline at end of file diff --git a/src/org/apollo/net/release/r377/OpenDialogueOverlayMessageEncoder.java b/src/org/apollo/net/release/r377/OpenDialogueOverlayMessageEncoder.java new file mode 100644 index 00000000..1f7f3ea6 --- /dev/null +++ b/src/org/apollo/net/release/r377/OpenDialogueOverlayMessageEncoder.java @@ -0,0 +1,24 @@ +package org.apollo.net.release.r377; + +import org.apollo.game.message.impl.OpenDialogueOverlayMessage; +import org.apollo.net.codec.game.DataOrder; +import org.apollo.net.codec.game.DataType; +import org.apollo.net.codec.game.GamePacket; +import org.apollo.net.codec.game.GamePacketBuilder; +import org.apollo.net.release.MessageEncoder; + +/** + * A {@link MessageEncoder} for the {@link OpenDialogueOverlayMessage}. + * + * @author Major + */ +public final class OpenDialogueOverlayMessageEncoder extends MessageEncoder { + + @Override + public GamePacket encode(OpenDialogueOverlayMessage message) { + GamePacketBuilder builder = new GamePacketBuilder(154); + builder.put(DataType.SHORT, DataOrder.LITTLE, message.getInterfaceId()); + return builder.toGamePacket(); + } + +} \ No newline at end of file diff --git a/src/org/apollo/net/release/r377/Release377.java b/src/org/apollo/net/release/r377/Release377.java index 4903d61d..01b663db 100644 --- a/src/org/apollo/net/release/r377/Release377.java +++ b/src/org/apollo/net/release/r377/Release377.java @@ -16,6 +16,7 @@ import org.apollo.game.message.impl.IgnoreListMessage; import org.apollo.game.message.impl.LogoutMessage; import org.apollo.game.message.impl.NpcSynchronizationMessage; import org.apollo.game.message.impl.OpenDialogueInterfaceMessage; +import org.apollo.game.message.impl.OpenDialogueOverlayMessage; import org.apollo.game.message.impl.OpenInterfaceMessage; import org.apollo.game.message.impl.OpenInterfaceSidebarMessage; import org.apollo.game.message.impl.OpenOverlayMessage; @@ -210,6 +211,7 @@ public final class Release377 extends Release { register(FlashTabInterfaceMessage.class, new FlashTabInterfaceMessageEncoder()); register(OpenSidebarMessage.class, new OpenSidebarMessageEncoder()); register(OpenOverlayMessage.class, new OpenOverlayMessageEncoder()); + register(OpenDialogueOverlayMessage.class, new OpenDialogueOverlayMessageEncoder()); } } \ No newline at end of file From 4efdfe79c753ed024724b02070a23053b3fd6a38 Mon Sep 17 00:00:00 2001 From: Ryley Kimmel Date: Fri, 27 Feb 2015 13:11:43 -0500 Subject: [PATCH 28/59] Rebase the resource provider; use NIO2 for HttpRequests. --- src/org/apollo/update/HttpRequestWorker.java | 21 +++---- .../apollo/update/JagGrabRequestWorker.java | 11 +--- .../resource/CombinedResourceProvider.java | 7 ++- .../resource/HypertextResourceProvider.java | 58 ++++++++++--------- .../update/resource/ResourceProvider.java | 19 +++--- .../resource/VirtualResourceProvider.java | 49 ++++++++-------- 6 files changed, 86 insertions(+), 79 deletions(-) diff --git a/src/org/apollo/update/HttpRequestWorker.java b/src/org/apollo/update/HttpRequestWorker.java index 5c7e82bb..de3e1954 100644 --- a/src/org/apollo/update/HttpRequestWorker.java +++ b/src/org/apollo/update/HttpRequestWorker.java @@ -9,11 +9,13 @@ import io.netty.handler.codec.http.HttpRequest; import io.netty.handler.codec.http.HttpResponse; import io.netty.handler.codec.http.HttpResponseStatus; -import java.io.File; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.charset.Charset; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.Date; +import java.util.Optional; import org.apollo.fs.IndexedFileSystem; import org.apollo.update.resource.CombinedResourceProvider; @@ -21,6 +23,8 @@ import org.apollo.update.resource.HypertextResourceProvider; import org.apollo.update.resource.ResourceProvider; import org.apollo.update.resource.VirtualResourceProvider; +import com.google.common.base.Charsets; + /** * A worker which services HTTP requests. * @@ -31,7 +35,7 @@ public final class HttpRequestWorker extends RequestWorker buf = provider.get(path); - ByteBuf wrapped; HttpResponseStatus status = HttpResponseStatus.OK; - String mime = getMimeType(request.getUri()); - if (buf == null) { + if (!buf.isPresent()) { status = HttpResponseStatus.NOT_FOUND; - wrapped = createErrorPage(status, "The page you requested could not be found."); mime = "text/html"; - } else { - wrapped = Unpooled.wrappedBuffer(buf); } + + ByteBuf wrapped = buf.isPresent() ? Unpooled.wrappedBuffer(buf.get()) : createErrorPage(status, "The page you requested could not be found."); HttpResponse response = new DefaultHttpResponse(request.getProtocolVersion(), status); diff --git a/src/org/apollo/update/JagGrabRequestWorker.java b/src/org/apollo/update/JagGrabRequestWorker.java index f763f7f8..d709ec78 100644 --- a/src/org/apollo/update/JagGrabRequestWorker.java +++ b/src/org/apollo/update/JagGrabRequestWorker.java @@ -1,12 +1,12 @@ package org.apollo.update; -import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; import io.netty.channel.ChannelFutureListener; import java.io.IOException; import java.nio.ByteBuffer; +import java.util.Optional; import org.apollo.fs.IndexedFileSystem; import org.apollo.net.codec.jaggrab.JagGrabRequest; @@ -38,13 +38,8 @@ public final class JagGrabRequestWorker extends RequestWorker buf = provider.get(request.getFilePath()); + buf.ifPresent(buffer -> channel.writeAndFlush(new JagGrabResponse(Unpooled.wrappedBuffer(buffer))).addListener(ChannelFutureListener.CLOSE)); } } \ No newline at end of file diff --git a/src/org/apollo/update/resource/CombinedResourceProvider.java b/src/org/apollo/update/resource/CombinedResourceProvider.java index b2487565..1395c55f 100644 --- a/src/org/apollo/update/resource/CombinedResourceProvider.java +++ b/src/org/apollo/update/resource/CombinedResourceProvider.java @@ -2,13 +2,14 @@ package org.apollo.update.resource; import java.io.IOException; import java.nio.ByteBuffer; +import java.util.Optional; /** * A resource provider composed of multiple resource providers. * * @author Graham */ -public final class CombinedResourceProvider extends ResourceProvider { +public final class CombinedResourceProvider implements ResourceProvider { /** * An array of resource providers. @@ -30,13 +31,13 @@ public final class CombinedResourceProvider extends ResourceProvider { } @Override - public ByteBuffer get(String path) throws IOException { + public Optional get(String path) throws IOException { for (ResourceProvider provider : providers) { if (provider.accept(path)) { return provider.get(path); } } - return null; + return Optional.empty(); } } \ No newline at end of file diff --git a/src/org/apollo/update/resource/HypertextResourceProvider.java b/src/org/apollo/update/resource/HypertextResourceProvider.java index 7b6fed1f..310d0135 100644 --- a/src/org/apollo/update/resource/HypertextResourceProvider.java +++ b/src/org/apollo/update/resource/HypertextResourceProvider.java @@ -1,62 +1,68 @@ package org.apollo.update.resource; -import java.io.File; import java.io.IOException; -import java.io.RandomAccessFile; import java.net.URI; import java.nio.ByteBuffer; +import java.nio.channels.FileChannel; import java.nio.channels.FileChannel.MapMode; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Optional; /** * A {@link ResourceProvider} which provides additional hypertext resources. * * @author Graham */ -public final class HypertextResourceProvider extends ResourceProvider { +public final class HypertextResourceProvider implements ResourceProvider { /** - * The base directory from which documents are served. + * The base {@link Path} from which documents are served. */ - private final File base; + private final Path base; /** - * Creates a new hypertext resource provider with the specified base directory. + * Creates a new hypertext resource provider with the specified base + * directory. * * @param base The base directory. */ - public HypertextResourceProvider(File base) { + public HypertextResourceProvider(Path base) { this.base = base; } @Override public boolean accept(String path) throws IOException { - File file = new File(base, path); - URI target = file.toURI().normalize(); - if (target.toASCIIString().startsWith(base.toURI().normalize().toASCIIString())) { - if (file.isDirectory()) { - file = new File(file, "index.html"); - } - return file.exists(); + Path file = base.resolve(path); + + URI target = file.toUri().normalize(); + if (!target.toASCIIString().startsWith(base.toUri().normalize().toASCIIString())) { + return false; } - return false; + + if (Files.isDirectory(file)) { + file = file.resolve("index.html"); + } + + return Files.exists(file); } @Override - public ByteBuffer get(String path) throws IOException { - File file = new File(base, path); - if (file.isDirectory()) { - file = new File(file, "index.html"); - } - if (!file.exists()) { - return null; + public Optional get(String path) throws IOException { + Path root = base.resolve(path); + + if (Files.isDirectory(root)) { + root = root.resolve("index.html"); } - ByteBuffer buffer; - try (RandomAccessFile raf = new RandomAccessFile(file, "r")) { - buffer = raf.getChannel().map(MapMode.READ_ONLY, 0, raf.length()); + if (!Files.exists(root)) { + return Optional.empty(); } - return buffer; + try (FileChannel channel = FileChannel.open(root)) { + ByteBuffer buf = channel.map(MapMode.READ_ONLY, 0, Files.size(root)); + return Optional.of(buf); + } } } \ No newline at end of file diff --git a/src/org/apollo/update/resource/ResourceProvider.java b/src/org/apollo/update/resource/ResourceProvider.java index f250b90f..5e06d37c 100644 --- a/src/org/apollo/update/resource/ResourceProvider.java +++ b/src/org/apollo/update/resource/ResourceProvider.java @@ -2,30 +2,33 @@ package org.apollo.update.resource; import java.io.IOException; import java.nio.ByteBuffer; +import java.util.Optional; /** * A class which provides resources. * * @author Graham */ -public abstract class ResourceProvider { +public interface ResourceProvider { /** * Checks that this provider can fulfil a request to the specified resource. * * @param path The path to the resource, e.g. {@code /crc}. - * @return {@code true} if the provider can fulfil a request to the resource, {@code false} otherwise. + * @return {@code true} if the provider can fulfil a request to the + * resource, {@code false} otherwise. * @throws IOException If an I/O error occurs. */ - public abstract boolean accept(String path) throws IOException; + public boolean accept(String path) throws IOException; /** - * Gets a resource by its path. + * Returns a resource as a {@link ByteBuffer} if it exists. * - * @param path The path. - * @return The resource, or {@code null} if it doesn't exist. - * @throws IOException If an I/O error occurs. + * @param path The path to the resource. + * @return A {@code ByteBuffer} representation of a resource if it exists + * otherwise {@link Optional#empty()} is returned. + * @throws IOException If some I/O exception occurs. */ - public abstract ByteBuffer get(String path) throws IOException; + public Optional get(String path) throws IOException; } \ No newline at end of file diff --git a/src/org/apollo/update/resource/VirtualResourceProvider.java b/src/org/apollo/update/resource/VirtualResourceProvider.java index 51d76326..f1a9d5de 100644 --- a/src/org/apollo/update/resource/VirtualResourceProvider.java +++ b/src/org/apollo/update/resource/VirtualResourceProvider.java @@ -2,22 +2,25 @@ package org.apollo.update.resource; import java.io.IOException; import java.nio.ByteBuffer; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import java.util.Optional; import org.apollo.fs.IndexedFileSystem; /** - * A {@link ResourceProvider} which maps virtual resources (such as {@code /media}) to files in an - * {@link IndexedFileSystem}. + * A {@link ResourceProvider} which maps virtual resources (such as + * {@code /media}) to files in an {@link IndexedFileSystem}. * * @author Graham */ -public final class VirtualResourceProvider extends ResourceProvider { +public final class VirtualResourceProvider implements ResourceProvider { /** - * An array of valid prefixes. + * A {@link List} of valid prefixes. */ - private static final String[] VALID_PREFIXES = { "crc", "title", "config", "interface", "media", "versionlist", "textures", - "wordenc", "sounds" }; + private static final List VALID_PREFIXES = Arrays.asList("/crc", "/title", "/config", "/interface", "/media", "/versionlist", "/textures", "/wordenc", "/sounds"); /** * The file system. @@ -26,7 +29,7 @@ public final class VirtualResourceProvider extends ResourceProvider { /** * Creates a new virtual resource provider with the specified file system. - * + * * @param fs The file system. */ public VirtualResourceProvider(IndexedFileSystem fs) { @@ -35,36 +38,34 @@ public final class VirtualResourceProvider extends ResourceProvider { @Override public boolean accept(String path) throws IOException { - for (String prefix : VALID_PREFIXES) { - if (path.startsWith("/" + prefix)) { - return true; - } - } - return false; + Objects.requireNonNull(path); + + return VALID_PREFIXES.stream().anyMatch(path::startsWith); } @Override - public ByteBuffer get(String path) throws IOException { + public Optional get(String path) throws IOException { if (path.startsWith("/crc")) { - return fs.getCrcTable(); + return Optional.of(fs.getCrcTable()); } else if (path.startsWith("/title")) { - return fs.getFile(0, 1); + return Optional.of(fs.getFile(0, 1)); } else if (path.startsWith("/config")) { - return fs.getFile(0, 2); + return Optional.of(fs.getFile(0, 2)); } else if (path.startsWith("/interface")) { - return fs.getFile(0, 3); + return Optional.of(fs.getFile(0, 3)); } else if (path.startsWith("/media")) { - return fs.getFile(0, 4); + return Optional.of(fs.getFile(0, 4)); } else if (path.startsWith("/versionlist")) { - return fs.getFile(0, 5); + return Optional.of(fs.getFile(0, 5)); } else if (path.startsWith("/textures")) { - return fs.getFile(0, 6); + return Optional.of(fs.getFile(0, 6)); } else if (path.startsWith("/wordenc")) { - return fs.getFile(0, 7); + return Optional.of(fs.getFile(0, 7)); } else if (path.startsWith("/sounds")) { - return fs.getFile(0, 8); + return Optional.of(fs.getFile(0, 8)); } - return null; + + return Optional.empty(); } } \ No newline at end of file From 46ffb7562678c33f715f20476f0f4e68c0677831 Mon Sep 17 00:00:00 2001 From: Ryley Kimmel Date: Fri, 27 Feb 2015 13:15:20 -0500 Subject: [PATCH 29/59] Explicitly close jag grab request channel if no resource is provided. --- src/org/apollo/update/JagGrabRequestWorker.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/org/apollo/update/JagGrabRequestWorker.java b/src/org/apollo/update/JagGrabRequestWorker.java index d709ec78..1be8de3f 100644 --- a/src/org/apollo/update/JagGrabRequestWorker.java +++ b/src/org/apollo/update/JagGrabRequestWorker.java @@ -1,5 +1,6 @@ package org.apollo.update; +import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; import io.netty.channel.ChannelFutureListener; @@ -39,7 +40,13 @@ public final class JagGrabRequestWorker extends RequestWorker buf = provider.get(request.getFilePath()); - buf.ifPresent(buffer -> channel.writeAndFlush(new JagGrabResponse(Unpooled.wrappedBuffer(buffer))).addListener(ChannelFutureListener.CLOSE)); + + if (buf.isPresent()) { + ByteBuf wrapped = Unpooled.wrappedBuffer(buf.get()); + channel.writeAndFlush(new JagGrabResponse(wrapped)).addListener(ChannelFutureListener.CLOSE); + } else { + channel.close(); + } } } \ No newline at end of file From da967209c06ec964b5fb45a4b9c8b52de68b0446 Mon Sep 17 00:00:00 2001 From: Ryley Kimmel Date: Fri, 27 Feb 2015 13:18:44 -0500 Subject: [PATCH 30/59] Reformat using 120 character line width rather than 80. --- src/org/apollo/update/HttpRequestWorker.java | 5 ++--- .../apollo/update/resource/HypertextResourceProvider.java | 3 +-- src/org/apollo/update/resource/ResourceProvider.java | 7 +++---- .../apollo/update/resource/VirtualResourceProvider.java | 4 ++-- 4 files changed, 8 insertions(+), 11 deletions(-) diff --git a/src/org/apollo/update/HttpRequestWorker.java b/src/org/apollo/update/HttpRequestWorker.java index de3e1954..b57f41b1 100644 --- a/src/org/apollo/update/HttpRequestWorker.java +++ b/src/org/apollo/update/HttpRequestWorker.java @@ -54,8 +54,7 @@ public final class HttpRequestWorker extends RequestWorker get(String path) throws IOException; diff --git a/src/org/apollo/update/resource/VirtualResourceProvider.java b/src/org/apollo/update/resource/VirtualResourceProvider.java index f1a9d5de..354d8927 100644 --- a/src/org/apollo/update/resource/VirtualResourceProvider.java +++ b/src/org/apollo/update/resource/VirtualResourceProvider.java @@ -10,8 +10,8 @@ import java.util.Optional; import org.apollo.fs.IndexedFileSystem; /** - * A {@link ResourceProvider} which maps virtual resources (such as - * {@code /media}) to files in an {@link IndexedFileSystem}. + * A {@link ResourceProvider} which maps virtual resources (such as {@code /media}) to files in an + * {@link IndexedFileSystem}. * * @author Graham */ From fd04bd4e53350503af3cbd5f22cb1b3f90e6a17b Mon Sep 17 00:00:00 2001 From: Major- Date: Fri, 27 Feb 2015 18:26:47 +0000 Subject: [PATCH 31/59] Rename ':serialized' attribute type to ':persistent'. --- data/plugins/entity/attributes/attributes.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/data/plugins/entity/attributes/attributes.rb b/data/plugins/entity/attributes/attributes.rb index 42261756..5deaa889 100644 --- a/data/plugins/entity/attributes/attributes.rb +++ b/data/plugins/entity/attributes/attributes.rb @@ -21,11 +21,11 @@ class Entity name = name[0...-1].strip # Drop the equals set_attribute(name, to_attribute(args[0])) - elsif AttributeMap::get_definition(name) == nil + elsif AttributeMap::get_definition(name).nil? super(symbol, *args) else attribute = get_attribute(name); definition = AttributeMap::get_definition(name) - value = attribute == nil ? definition.default : attribute.value + value = attribute.nil? ? definition.default : attribute.value return definition.type == AttributeType::SYMBOL ? value.to_sym : value end @@ -64,7 +64,7 @@ end # Gets the Persistence type of the specified value. def get_persistence(persistence) - raise "Undefined persistence type #{persistence}." unless persistence == :serialized || persistence == :transient + raise "Undefined persistence type #{persistence}." unless persistence == :persistent || persistence == :transient - return persistence == :serialized ? AttributePersistence::SERIALIZED : AttributePersistence::TRANSIENT + return persistence == :persistent ? AttributePersistence::SERIALIZED : AttributePersistence::TRANSIENT end \ No newline at end of file From f6046cce23564f39618d82ce31c4425c85c0ad8e Mon Sep 17 00:00:00 2001 From: Major- Date: Fri, 27 Feb 2015 18:27:23 +0000 Subject: [PATCH 32/59] Add basic prayer support. --- data/plugins/skill/prayer/plugin.xml | 7 ++- data/plugins/skill/prayer/prayers.rb | 89 ++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+), 2 deletions(-) create mode 100644 data/plugins/skill/prayer/prayers.rb diff --git a/data/plugins/skill/prayer/plugin.xml b/data/plugins/skill/prayer/plugin.xml index 3d6a402c..edbeb441 100644 --- a/data/plugins/skill/prayer/plugin.xml +++ b/data/plugins/skill/prayer/plugin.xml @@ -1,7 +1,7 @@ skill-prayer - 1 + 0.9 Prayer Adds the Prayer skill. @@ -10,6 +10,9 @@ + - + + attributes + \ No newline at end of file diff --git a/data/plugins/skill/prayer/prayers.rb b/data/plugins/skill/prayer/prayers.rb new file mode 100644 index 00000000..788b843e --- /dev/null +++ b/data/plugins/skill/prayer/prayers.rb @@ -0,0 +1,89 @@ + +java_import 'org.apollo.game.message.impl.ConfigMessage' + +# Declares the active prayer attribute. +declare_attribute(:active_prayer, -1, :persistent) + + +# The hash of button ids to prayers. +PRAYERS = {} + +# Intercept the ButtonMessage to toggle a prayer. +on :message, :button do |ctx, player, message| + button = message.widget_id + prayer = PRAYERS[button] + + unless prayer.nil? + if (prayer.level > player.skill_set.get_maximum_level(Skill::PRAYER)) + update_setting(player, prayer, :off) + next + end + player.send_message("after level check") + + previous = player.active_prayer + + unless previous == -1 + update_setting(player, PRAYERS[previous], :off) + end + + if previous != button + player.send_message("Previous: #{previous}, new: #{button}.") + update_setting(player, prayer, :on) + player.active_prayer = button + end + end +end + +private + +# A Prayer that can be activated by a player. +class Prayer + attr_reader :name, :level, :button, :setting, :drain + + def initialize(name, level, button, setting, drain) + @name = name + @level = level + @button = button + @setting = setting + @drain = drain + end + +end + +def update_setting(player, prayer, state) + value = (state == :on) ? 1 : 0 + player.send_message("Toggling prayer #{prayer.name}, state: #{state}.") + player.send(ConfigMessage.new(prayer.setting, value)) +end + +# Appends a Prayer to the hash. +def append_prayer(properties) + raise 'Error: prayer properties hash must contain a name, level, button, setting, and drain.' unless properties.has_keys?(:name, :level, :button, :setting, :drain) + + button = properties[:button] + PRAYERS[button] = Prayer.new(properties[:name], properties[:level], button, properties[:setting], properties[:drain]) +end + +# Don't deal with the actual effect here to avoid mess (TODO do it, but with attributes?). +append_prayer name: :thick_skin, level: 1, button: 5609, setting: 83, drain: 0.01 +append_prayer name: :burst_of_strength, level: 4, button: 5610, setting: 84, drain: 0.01 +append_prayer name: :clarity_of_thought, level: 7, button: 5611, setting: 85, drain: 0.01 +append_prayer name: :rock_skin, level: 10, button: 5612, setting: 86, drain: 0.04 +append_prayer name: :superhuman_strength, level: 13, button: 5613, setting: 87, drain: 0.04 +append_prayer name: :improved_reflexes, level: 16, button: 5614, setting: 88, drain: 0.04 + +append_prayer name: :rapid_restore, level: 19, button: 5615, setting: 89, drain: 0.01 +append_prayer name: :rapid_heal, level: 22, button: 5615, setting: 90, drain: 0.01 +append_prayer name: :protect_item, level: 25, button: 5617, setting: 91, drain: 0.01 + +append_prayer name: :steel_skin, level: 28, button: 5618, setting: 92, drain: 0.1 +append_prayer name: :ultimate_strength, level: 31, button: 5619, setting: 93, drain: 0.1 +append_prayer name: :incredible_reflexes, level: 34, button: 5620, setting: 94, drain: 0.1 + +append_prayer name: :protect_from_magic, level: 37, button: 5621, setting: 95, drain: 0.15 +append_prayer name: :protect_from_missiles, level: 40, button: 5622, setting: 96, drain: 0.15 +append_prayer name: :protect_from_melee, level: 43, button: 5633, setting: 97, drain: 0.15 + +append_prayer name: :retribution, level: 46, button: 683, setting: 98, drain: 0.15 +append_prayer name: :redemption, level: 49, button: 684, setting: 99, drain: 0.15 +append_prayer name: :smite, level: 52, button: 685, setting: 100, drain: 0.2 \ No newline at end of file From dabca79661c7c8ef74b66299b17b02cae8832692 Mon Sep 17 00:00:00 2001 From: Major- Date: Fri, 27 Feb 2015 18:27:49 +0000 Subject: [PATCH 33/59] Add /lib/ to gitignore. --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 07a10d66..e3e103fa 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ /data/fs /data/savedGames /bin/ +/lib/ \ No newline at end of file From fd9009aecb4f1604921bff7e8b60e3d384a01fdd Mon Sep 17 00:00:00 2001 From: Major- Date: Fri, 27 Feb 2015 19:03:03 +0000 Subject: [PATCH 34/59] Add imports to command.rb. --- data/plugins/util/command.rb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/data/plugins/util/command.rb b/data/plugins/util/command.rb index 7607c062..0e86d618 100644 --- a/data/plugins/util/command.rb +++ b/data/plugins/util/command.rb @@ -1,3 +1,9 @@ +require 'java' + +java_import 'org.apollo.game.model.def.ItemDefinition' +java_import 'org.apollo.game.model.def.NpcDefinition' +java_import 'org.apollo.game.model.def.ObjectDefinition' + # Checks whether the amount of arguments provided is correct, sending the player the specified message if not. def valid_arg_length(args, length, player, message) From 8bb537ce7c57c00401a493c80158cdfb45d8a308 Mon Sep 17 00:00:00 2001 From: Major- Date: Fri, 27 Feb 2015 19:07:22 +0000 Subject: [PATCH 35/59] Add Conversation support, make numerous bug fixes and code improvements. --- data/plugins/dialogue/dialogue.rb | 281 ++++++++++++++++++------------ 1 file changed, 173 insertions(+), 108 deletions(-) diff --git a/data/plugins/dialogue/dialogue.rb b/data/plugins/dialogue/dialogue.rb index 301cf771..55b27531 100644 --- a/data/plugins/dialogue/dialogue.rb +++ b/data/plugins/dialogue/dialogue.rb @@ -7,26 +7,62 @@ java_import 'org.apollo.game.message.impl.SetWidgetNpcModelMessage' java_import 'org.apollo.game.message.impl.SetWidgetPlayerModelMessage' java_import 'org.apollo.game.message.impl.SetWidgetTextMessage' -# Defines a dialogue, with the specified name and block. -def dialogue(name, &block) - raise 'Dialogues must have a name and block.' if (name.nil? || block.nil?) +# The map of conversation names to Conversations. +CONVERSATIONS = {} - dialogue = Dialogue.new(name) - dialogue.instance_eval(&block) - dialogue.wrap - DIALOGUES[name] = dialogue + +# Declares a conversation. +def conversation(name, &block) + conversation = Conversation.new(name) + conversation.instance_eval(&block) + CONVERSATIONS[name] = conversation end -# Defines an opening (i.e. conversation starter) dialogue, which hooks into the chain. -# Allows for a lambda prerequisite to be passed, which takes one argument the player; if the prerequisite evaluates to false, the dialogue will not be opened. -def opening_dialogue(name, prerequisite=nil, &block) - dialogue = dialogue(name, &block) - npc = dialogue.npc - raise 'Npc cannot be null when opening a dialogue.' if npc.nil? +# A conversation held between two entities. +class Conversation - on :message, :first_npc_action, npc do |ctx, player, event| - player.open_dialogue(name) if (prerequisite.nil? || prerequisite.call(player)) + # Creates the Conversation. + def initialize(name) + @dialogues = {} + @starters = [] + @name = name end + + # Defines a dialogue, with the specified name and block. + def dialogue(name, &block) + raise 'Dialogues must have a name and block.' if (name.nil? || block.nil?) + + dialogue = Dialogue.new(name, self) + dialogue.instance_eval(&block) + dialogue.wrap + @dialogues[name] = dialogue + + if ((@dialogues.empty? || dialogue.has_precondition) && dialogue.type == :npc_speech) + npc = dialogue.npc + raise 'Npc cannot be null when opening a dialogue.' if npc.nil? + @starters << dialogue + + on :message, :first_npc_action do |ctx, player, event| + id = $world.npc_repository.get(event.index).id + if npc == id + @starters.each do |start| + if dialogue.precondition(player) + send_dialogue(player, dialogue) + ctx.break_handler_chain() + break + end + end + end + end + end + end + + # Gets part of a conversation (i.e. a dialogue). + def part(name) + raise "Conversation #{@name} does not contain a dialogue called #{name}." unless @dialogues.has_key?(name) + @dialogues[name] + end + end # Declares an emote, with the specified name and id. @@ -35,12 +71,26 @@ def declare_emote(name, id) end +# Sends the specified dialogue. +def send_dialogue(player, dialogue) + type = dialogue.type + action = dialogue.action + action.call(player) unless action.nil? + + case type + when :message_with_item then send_item_dialogue(player, dialogue) + when :message_with_model then send_model_dialogue(player, dialogue) + when :npc_speech then send_npc_dialogue(player, dialogue) + when :options then send_options_dialogue(player, dialogue) + when :player_speech then send_player_dialogue(player, dialogue) + when :text then send_text_dialogue(player, dialogue) + when :statement then send_statement_dialogue(player, dialogue) + else raise "Unrecognised dialogue type #{type}." + end +end private -# The hash of dialogue names to dialogues. -DIALOGUES = {} - # The hash of emote names to ids. EMOTES = {} @@ -50,23 +100,33 @@ MAXIMUM_LINE_COUNT = 4 # The maximum amount of options that can be displayed on a dialogue. MAXIMUM_OPTION_COUNT = 5 -# The maximum width of a line, in characters. -MAXIMUM_LINE_WIDTH = 55 +# The maximum width of a line, in pixels, for a dialogue with media. +MAXIMUM_MEDIA_LINE_WIDTH = 350 + +# The maximum width of a line, in pixels, for a dialogue with no media. +MAXIMUM_LINE_WIDTH = 430 # The possible types of a dialogue. -DIALOGUE_TYPES = [ :message_with_item, :message_with_model, :npc_speech, :options, :player_speech, :text ] +DIALOGUE_TYPES = [ :message_with_item, :message_with_model, :npc_speech, :options, :player_speech, :statement, :text ] # A type of dialogue. class Dialogue attr_reader :emote, :name, :media, :options, :text, :title, :type # Initializes the Dialogue. - def initialize(name) + def initialize(name, conversation) @name = name.to_s + @conversation = conversation @text = [] @options = [] end + # An action that is executed when the dialogue is displayed. + def action(&block) + @action = block unless block.nil? + @action + end + # Closes the dialogue interface when the player clicks the 'Click here to continue...' text. def close continue(:close => true) @@ -77,16 +137,36 @@ class Dialogue raise 'Cannot add a continue event on a dialogue with options.' unless @options.size.zero? raise 'Must declare either a type or a block for a continue event.' if (type.nil? && block.nil?) - @options << (block.nil? ? get_next_dialogue(type) : block) + action = get_next_dialogue(type) unless type.nil? + @options << ->(player) { action.call(player) unless type.nil?; block.call(player) unless block.nil? } + end + + # Copies the value of every variable from the specified Dialogue, optionally updating the text array. + def copy_from(dialogue, text=nil) + @emote = dialogue.emote + @item = dialogue.item + @model = dialogue.model + @npc = dialogue.npc + @options = dialogue.options + @text = if text.nil? then dialogue.text.dup else text.dup end + @type = dialogue.type end # Sets the emote performed by the dialogue head. def emote(emote=nil) - raise 'Can only perform an emote on :player_speech or :npc_speech dialogues.' unless [ :npc_speech, :player_speech ].include?(@type) - @emote = EMOTES[emote] if emote.kind_of?(Symbol) + unless emote.nil? + raise 'Can only perform an emote on :player_speech or :npc_speech dialogues.' unless [ :npc_speech, :player_speech ].include?(@type) + @emote = emote.kind_of?(Symbol) ? EMOTES[emote] : emote + end + @emote end + # Returns whether or not this dialogue has a precondition. + def has_precondition + !@precondition.nil? + end + # Gets the media of this dialogue. def media() case @type @@ -120,8 +200,10 @@ class Dialogue # Sets the id of the npc displayed. def npc(npc=nil) - raise 'Can only display an npc on :npc_speech dialogues.' unless @type == :npc_speech - @npc = lookup_npc(npc) unless npc.nil? + unless npc.nil? + raise 'Can only display an npc on :npc_speech dialogues.' unless @type == :npc_speech + @npc = lookup_npc(npc) + end @npc end @@ -136,15 +218,18 @@ class Dialogue # Gets the array of options. def options - @options.dup + @options.dup + end + + # Sets the precondition of this dialogue. + def precondition(player=nil, &block) + @precondition = block unless block.nil? + @precondition.call(player) unless player.nil? end # Appends a message to the text list. def text(*message) - unless message.nil? - @text.concat(message) - end - + @text.concat(message) unless message.nil? @text end @@ -166,46 +251,43 @@ class Dialogue # Wraps text in this Dialogue, inserting extra Dialogues in the chain if necessary. def wrap - lines = [] next if @type == :options + lines = [] + maximum_width = [ :text, :statement ].include?(@type) ? MAXIMUM_LINE_WIDTH : MAXIMUM_MEDIA_LINE_WIDTH + maximum_lines = MAXIMUM_LINE_COUNT - text = @text[0] - segments = []# text.chars.each_slice(MAXIMUM_LINE_WIDTH).map(&:join) # Split text into array of strings with length <= 60. - previous = 0; index = MAXIMUM_LINE_WIDTH + text = @text.first + segments = [] + index = 0; width = 0; space = 0 while index < text.length - index -= 1 until text[index] == ' ' - segments << text[previous..index] - previous = index - index += MAXIMUM_LINE_WIDTH - end - segments << text[previous..text.length] + char = text[index] + space = index if char == ' ' + width += get_width(char) + index += 1 - if (segments.size <= MAXIMUM_LINE_COUNT) + if (width >= maximum_width) + segments << text[0..space] + text = text[(space + 1)..-1] + width = index = space = 0 + end + end + + segments << text + + if (segments.size <= maximum_lines) lines.concat(segments) - @text = @text.drop(1) + @text = @text[1..-1] insert_copy(@text) if @text.size > 0 else - remaining = MAXIMUM_LINE_COUNT - segments.size - lines.concat(segments.first(remaining)) - insert_copy(segments.drop(remaining).join().concat(@text.drop(1))) + lines.concat(segments.first(maximum_lines)) + segments = [ segments.drop(maximum_lines).join() ] + insert_copy(segments << @text[1..-1].join()) end @text = lines end - - # Copies the value of every variable from the specified Dialogue, optionally updating the text array. - def copy_from(dialogue, text=nil) - @emote = dialogue.emote - @item = dialogue.item - @model = dialogue.model - @npc = dialogue.npc - @options = dialogue.options - @text = if text.nil? then dialogue.text.dup else text.dup end - @type = dialogue.type - end - private # Inserts a copy of this Dialogue into the chain, but with different text. @@ -217,11 +299,10 @@ class Dialogue index ||= -1 name = "#{name[0..index]}-auto-inserted-#{id}" - dialogue = Dialogue.new(name) + dialogue = Dialogue.new(name, @conversation) dialogue.copy_from(self, text.dup) dialogue.wrap() - DIALOGUES[name] = dialogue @options[0] = ->(player) { send_dialogue(player, dialogue) } end @@ -229,10 +310,9 @@ class Dialogue def get_next_dialogue(hash) hash.keys.each do |key| case key - when :close - return ->(player) { player.send(CloseInterfaceMessage.new) } - when :dialogue - return ->(player) { send_dialogue(player, lookup_dialogue(hash[key])) } + when :disabled then return ->(player) { } + when :close then return ->(player) { player.send(CloseInterfaceMessage.new) } + when :dialogue then return ->(player) { send_dialogue(player, @conversation.part(hash[key])) } else raise "Unrecognised dialogue continue type #{key}." end end @@ -240,41 +320,11 @@ class Dialogue end -# The existing Player class. -class Player +# The dialogue interface ids for dialogues that only display text, but with no 'Click here to continue...' message. +STATEMENT_DIALOGUE_IDS = [ 12788, 12790, 12793, 12797, 6179 ] # TODO - # Opens the dialogue with the specified name. - def open_dialogue(name) - dialogue = lookup_dialogue(name) - send_dialogue(self, dialogue) - end - -end - - - -# Gets a Dialogue using the name it was registered with. -def lookup_dialogue(name) - dialogue = DIALOGUES[name] - raise "No dialogue named #{name.to_s}." if dialogue.nil? - - dialogue -end - -# Sends the specified dialogue. -def send_dialogue(player, dialogue) - type = dialogue.type - - case type - when :message_with_item then send_item_dialogue(player, dialogue) - when :message_with_model then send_model_dialogue(player, dialogue) - when :npc_speech then send_npc_dialogue(player, dialogue) - when :options then send_options_dialogue(player, dialogue) - when :player_speech then send_player_dialogue(player, dialogue) - when :text then send_text_dialogue(player, dialogue) - else raise "Unrecognised dialogue type #{type}." - end -end +# The dialogue interface ids for dialogues that display an item and text, ordered by line count. +ITEM_DIALOGUE_IDS = [ 306, 310, 315, 321 ] # The dialogue interface ids for dialogues that only display text, ordered by line count. TEXT_DIALOGUE_IDS = [ 356, 359, 363, 368, 374 ] @@ -288,6 +338,21 @@ NPC_DIALOGUE_IDS = [ 4882, 4887, 4893, 4900 ] # The dialogue interface ids for option dialogues, ordered by (option_count - 1) OPTIONS_DIALOGUE_IDS = [ 2459, 2469, 2480, 2492 ] + + +## TODO separate this into different Dialogue types ## + + +# Sends a dialogue displaying only text, with no 'Click here to continue...' button. +def send_statement_dialogue(player, dialogue) + text = dialogue.text + dialogue_id = STATEMENT_DIALOGUE_IDS[text.size] + + set_text(player, dialogue_id + 1, dialogue.title) + text.each_with_index { |line, index| set_text(player, dialogue_id + 2 + index, line) } + player.interface_set.open_dialogue_overlay(dialogue_id) +end + # Sends a dialogue displaying only text. def send_text_dialogue(player, dialogue) title = dialogue.title @@ -296,7 +361,7 @@ end # Sends a dialogue displaying the player's head. def send_player_dialogue(player, dialogue) - send_generic_dialogue(player, dialogue, PLAYERS_DIALOGUE_IDS, ->(id) { SetWidgetPlayerModelMessage.new(id + 1) }) + send_generic_dialogue(player, dialogue, player.username, PLAYER_DIALOGUE_IDS, ->(id) { SetWidgetPlayerModelMessage.new(id + 1) }) end # Sends a dialogue displaying the head of an npc. @@ -308,7 +373,6 @@ def send_npc_dialogue(player, dialogue) send_generic_dialogue(player, dialogue, name, NPC_DIALOGUE_IDS, ->(id) { SetWidgetNpcModelMessage.new(id + 1, npc)}) end - # Sends a dialogue displaying an event. def send_generic_dialogue(player, dialogue, title, ids, event=nil) text = dialogue.text @@ -317,8 +381,8 @@ def send_generic_dialogue(player, dialogue, title, ids, event=nil) set_text(player, dialogue_title_id(dialogue_id), title) - text.each_index { |index| set_text(player, dialogue_text_id(dialogue_id, index), text[index]) } - player.interface_set.open_dialogue(ContinueDialogueAdapter.new(player, dialogue.options[0]), dialogue_id) # TODO listener!!! + text.each_with_index { |line, index| set_text(player, dialogue_text_id(dialogue_id, index), line) } + player.interface_set.open_dialogue(ContinueDialogueAdapter.new(player, dialogue.options[0]), dialogue_id) end @@ -334,8 +398,8 @@ def send_options_dialogue(player, dialogue) question = dialogue.title set_text(player, dialogue_question_id(dialogue_id), question) - text.each_index { |index| set_text(player, dialogue_option_id(dialogue_id, index), text[index]) } - player.interface_set.open_dialogue(OptionDialogueAdapter.new(player, options), dialogue_id) # TODO listener!!! + text.each_with_index { |line, index| set_text(player, dialogue_option_id(dialogue_id, index), line) } + player.interface_set.open_dialogue(OptionDialogueAdapter.new(player, options), dialogue_id) end @@ -344,7 +408,7 @@ class ContinueDialogueAdapter < DialogueAdapter # Creates the ContinueDialogueAdadpter. def initialize(player, continue) - super() + super() @player = player @continue = continue end @@ -362,7 +426,7 @@ class OptionDialogueAdapter < DialogueAdapter # Creates the OptionDialogueAdadpter. def initialize(player, options) - super() + super() @player = player @options = options.dup end @@ -421,6 +485,7 @@ GLYPH_SPACING = [ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 8, 8, 8, 8, 8, 8, 8, 8, 8, 13, 6, 8, 8, 8, 8, 4, 4, 5, 4, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ] +# Gets the width of a single character. def get_width(char) - + return GLYPH_SPACING[char.ord] end \ No newline at end of file From 42f9456a97da0f1752caba108aa48f9e6321eb89 Mon Sep 17 00:00:00 2001 From: Major- Date: Fri, 27 Feb 2015 19:13:53 +0000 Subject: [PATCH 36/59] Raise errors if conversation or dialogues already exist. --- data/plugins/dialogue/dialogue.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/data/plugins/dialogue/dialogue.rb b/data/plugins/dialogue/dialogue.rb index 55b27531..8c954c0e 100644 --- a/data/plugins/dialogue/dialogue.rb +++ b/data/plugins/dialogue/dialogue.rb @@ -15,6 +15,8 @@ CONVERSATIONS = {} def conversation(name, &block) conversation = Conversation.new(name) conversation.instance_eval(&block) + + raise "Conversation named #{name} already exists." if CONVERSATIONS.has_key?(name) CONVERSATIONS[name] = conversation end @@ -35,6 +37,8 @@ class Conversation dialogue = Dialogue.new(name, self) dialogue.instance_eval(&block) dialogue.wrap + + raise "Conversations #{@name} already has a dialogue named #{name}." if @dialogues.has_key?(name) @dialogues[name] = dialogue if ((@dialogues.empty? || dialogue.has_precondition) && dialogue.type == :npc_speech) From f059d8da03348cd81f0deb5900aa42e22f86fbee Mon Sep 17 00:00:00 2001 From: Ryley Kimmel Date: Fri, 27 Feb 2015 14:22:26 -0500 Subject: [PATCH 37/59] Fix resource leak and unnecessary recursion when invalid requests are received. --- src/org/apollo/net/ApolloHandler.java | 32 +++++++--- .../net/codec/handshake/HandshakeDecoder.java | 61 +++++++++++-------- 2 files changed, 57 insertions(+), 36 deletions(-) diff --git a/src/org/apollo/net/ApolloHandler.java b/src/org/apollo/net/ApolloHandler.java index ad51eb83..d6b00b91 100644 --- a/src/org/apollo/net/ApolloHandler.java +++ b/src/org/apollo/net/ApolloHandler.java @@ -5,6 +5,8 @@ import io.netty.channel.ChannelHandler.Sharable; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.handler.codec.http.HttpRequest; +import io.netty.util.Attribute; +import io.netty.util.ReferenceCountUtil; import java.util.logging.Level; import java.util.logging.Logger; @@ -65,25 +67,37 @@ public final class ApolloHandler extends ChannelInboundHandlerAdapter { @Override public void channelRead(ChannelHandlerContext ctx, Object message) { - if (ctx.attr(NetworkConstants.SESSION_KEY).get() == null) { + try { + Attribute attr = ctx.attr(NetworkConstants.SESSION_KEY); + + Session session = attr.get(); + + if (session != null) { + session.messageReceived(message); + return; + } + if (message instanceof HttpRequest || message instanceof JagGrabRequest) { - new UpdateSession(ctx.channel(), serverContext).messageReceived(message); - } else { + session = new UpdateSession(ctx.channel(), serverContext); + } + + // TODO: Perhaps let HandshakeMessage implement Message to remove this explicit check + if (message instanceof HandshakeMessage) { HandshakeMessage handshakeMessage = (HandshakeMessage) message; switch (handshakeMessage.getServiceId()) { case HandshakeConstants.SERVICE_GAME: - ctx.attr(NetworkConstants.SESSION_KEY).set(new LoginSession(ctx, serverContext)); + attr.set(new LoginSession(ctx, serverContext)); break; + case HandshakeConstants.SERVICE_UPDATE: - ctx.attr(NetworkConstants.SESSION_KEY).set(new UpdateSession(ctx.channel(), serverContext)); + attr.set(new UpdateSession(ctx.channel(), serverContext)); break; - default: - throw new IllegalStateException("Invalid service id."); } } - } else { - ctx.attr(NetworkConstants.SESSION_KEY).get().messageReceived(message); + + } finally { + ReferenceCountUtil.release(message); } } diff --git a/src/org/apollo/net/codec/handshake/HandshakeDecoder.java b/src/org/apollo/net/codec/handshake/HandshakeDecoder.java index a0bf1020..b4f7f111 100644 --- a/src/org/apollo/net/codec/handshake/HandshakeDecoder.java +++ b/src/org/apollo/net/codec/handshake/HandshakeDecoder.java @@ -5,6 +5,7 @@ import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.ByteToMessageDecoder; import java.util.List; +import java.util.logging.Logger; import org.apollo.net.codec.login.LoginDecoder; import org.apollo.net.codec.login.LoginEncoder; @@ -19,35 +20,41 @@ import org.apollo.net.codec.update.UpdateEncoder; */ public final class HandshakeDecoder extends ByteToMessageDecoder { + /** + * The logger for this class. + */ + private static final Logger logger = Logger.getLogger(HandshakeDecoder.class.getName()); + @Override - protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List out) { - if (buffer.isReadable()) { - int id = buffer.readUnsignedByte(); - - switch (id) { - case HandshakeConstants.SERVICE_GAME: - ctx.pipeline().addFirst("loginEncoder", new LoginEncoder()); - ctx.pipeline().addAfter("handshakeDecoder", "loginDecoder", new LoginDecoder()); - break; - case HandshakeConstants.SERVICE_UPDATE: - ctx.pipeline().addFirst("updateEncoder", new UpdateEncoder()); - ctx.pipeline().addBefore("handler", "updateDecoder", new UpdateDecoder()); - ByteBuf buf = ctx.alloc().buffer(8); - buf.writeLong(0); - ctx.channel().writeAndFlush(buf); - break; - default: - throw new IllegalArgumentException("Invalid service id."); - } - - ctx.pipeline().remove(this); - HandshakeMessage message = new HandshakeMessage(id); - - out.add(message); - if (buffer.isReadable()) { - out.add(buffer.readBytes(buffer.readableBytes())); - } + protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List out) throws Exception { + if (!buffer.isReadable()) { + return; } + + int id = buffer.readUnsignedByte(); + + switch (id) { + case HandshakeConstants.SERVICE_GAME: + ctx.pipeline().addFirst("loginEncoder", new LoginEncoder()); + ctx.pipeline().addAfter("handshakeDecoder", "loginDecoder", new LoginDecoder()); + break; + + case HandshakeConstants.SERVICE_UPDATE: + ctx.pipeline().addFirst("updateEncoder", new UpdateEncoder()); + ctx.pipeline().addBefore("handler", "updateDecoder", new UpdateDecoder()); + + ByteBuf buf = ctx.alloc().buffer(8).writeLong(0); + ctx.channel().writeAndFlush(buf); + break; + + default: + ByteBuf data = buffer.readBytes(buffer.readableBytes()); + logger.info(String.format("Unecpected handshake request received: %d data: %s", id, data.toString())); + return; + } + + ctx.pipeline().remove(this); + out.add(new HandshakeMessage(id)); } } \ No newline at end of file From 39ccf3ae2bd76701b855baef9e6d320db2874b61 Mon Sep 17 00:00:00 2001 From: Ryley Kimmel Date: Fri, 27 Feb 2015 14:26:04 -0500 Subject: [PATCH 38/59] Fix typo and remove thrown exception. --- src/org/apollo/net/ApolloHandler.java | 8 ++++---- src/org/apollo/net/codec/handshake/HandshakeDecoder.java | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/org/apollo/net/ApolloHandler.java b/src/org/apollo/net/ApolloHandler.java index d6b00b91..91a12c80 100644 --- a/src/org/apollo/net/ApolloHandler.java +++ b/src/org/apollo/net/ApolloHandler.java @@ -72,15 +72,15 @@ public final class ApolloHandler extends ChannelInboundHandlerAdapter { Session session = attr.get(); + if (message instanceof HttpRequest || message instanceof JagGrabRequest) { + session = new UpdateSession(ctx.channel(), serverContext); + } + if (session != null) { session.messageReceived(message); return; } - if (message instanceof HttpRequest || message instanceof JagGrabRequest) { - session = new UpdateSession(ctx.channel(), serverContext); - } - // TODO: Perhaps let HandshakeMessage implement Message to remove this explicit check if (message instanceof HandshakeMessage) { HandshakeMessage handshakeMessage = (HandshakeMessage) message; diff --git a/src/org/apollo/net/codec/handshake/HandshakeDecoder.java b/src/org/apollo/net/codec/handshake/HandshakeDecoder.java index b4f7f111..31da920c 100644 --- a/src/org/apollo/net/codec/handshake/HandshakeDecoder.java +++ b/src/org/apollo/net/codec/handshake/HandshakeDecoder.java @@ -26,7 +26,7 @@ public final class HandshakeDecoder extends ByteToMessageDecoder { private static final Logger logger = Logger.getLogger(HandshakeDecoder.class.getName()); @Override - protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List out) throws Exception { + protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List out) { if (!buffer.isReadable()) { return; } @@ -49,7 +49,7 @@ public final class HandshakeDecoder extends ByteToMessageDecoder { default: ByteBuf data = buffer.readBytes(buffer.readableBytes()); - logger.info(String.format("Unecpected handshake request received: %d data: %s", id, data.toString())); + logger.info(String.format("Unexpected handshake request received: %d data: %s", id, data.toString())); return; } From bb2ef1435f674ba312844c72f275fb45666068da Mon Sep 17 00:00:00 2001 From: Ryley Kimmel Date: Fri, 27 Feb 2015 14:26:59 -0500 Subject: [PATCH 39/59] Rename attr -> attribute, remove unnecessary whitespace. --- src/org/apollo/net/ApolloHandler.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/org/apollo/net/ApolloHandler.java b/src/org/apollo/net/ApolloHandler.java index 91a12c80..ce0adfc9 100644 --- a/src/org/apollo/net/ApolloHandler.java +++ b/src/org/apollo/net/ApolloHandler.java @@ -68,9 +68,8 @@ public final class ApolloHandler extends ChannelInboundHandlerAdapter { @Override public void channelRead(ChannelHandlerContext ctx, Object message) { try { - Attribute attr = ctx.attr(NetworkConstants.SESSION_KEY); - - Session session = attr.get(); + Attribute attribute = ctx.attr(NetworkConstants.SESSION_KEY); + Session session = attribute.get(); if (message instanceof HttpRequest || message instanceof JagGrabRequest) { session = new UpdateSession(ctx.channel(), serverContext); @@ -87,11 +86,11 @@ public final class ApolloHandler extends ChannelInboundHandlerAdapter { switch (handshakeMessage.getServiceId()) { case HandshakeConstants.SERVICE_GAME: - attr.set(new LoginSession(ctx, serverContext)); + attribute.set(new LoginSession(ctx, serverContext)); break; case HandshakeConstants.SERVICE_UPDATE: - attr.set(new UpdateSession(ctx.channel(), serverContext)); + attribute.set(new UpdateSession(ctx.channel(), serverContext)); break; } } From 3c6ff3b370f7efc9521adf3b751a761a1926b220 Mon Sep 17 00:00:00 2001 From: Ryley Kimmel Date: Fri, 27 Feb 2015 16:39:41 -0500 Subject: [PATCH 40/59] Rename buf -> buffer, fixed documentation. --- src/org/apollo/update/JagGrabRequestWorker.java | 6 +++--- src/org/apollo/update/resource/ResourceProvider.java | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/org/apollo/update/JagGrabRequestWorker.java b/src/org/apollo/update/JagGrabRequestWorker.java index 1be8de3f..6f8c9528 100644 --- a/src/org/apollo/update/JagGrabRequestWorker.java +++ b/src/org/apollo/update/JagGrabRequestWorker.java @@ -39,10 +39,10 @@ public final class JagGrabRequestWorker extends RequestWorker buf = provider.get(request.getFilePath()); + Optional buffer = provider.get(request.getFilePath()); - if (buf.isPresent()) { - ByteBuf wrapped = Unpooled.wrappedBuffer(buf.get()); + if (buffer.isPresent()) { + ByteBuf wrapped = Unpooled.wrappedBuffer(buffer.get()); channel.writeAndFlush(new JagGrabResponse(wrapped)).addListener(ChannelFutureListener.CLOSE); } else { channel.close(); diff --git a/src/org/apollo/update/resource/ResourceProvider.java b/src/org/apollo/update/resource/ResourceProvider.java index 21053824..2c6f9960 100644 --- a/src/org/apollo/update/resource/ResourceProvider.java +++ b/src/org/apollo/update/resource/ResourceProvider.java @@ -21,7 +21,7 @@ public interface ResourceProvider { public boolean accept(String path) throws IOException; /** - * Returns a resource as a {@link ByteBuffer} if it exists. + * The resource data, as a {@link ByteBuffer}, wrapped in an {@link Optional}. * * @param path The path to the resource. * @return A {@code ByteBuffer} representation of a resource if it exists otherwise {@link Optional#empty()} is From dc8b093bf361245be4f8d0f4ee4e130f46c60b4b Mon Sep 17 00:00:00 2001 From: Major- Date: Sat, 28 Feb 2015 03:41:29 +0000 Subject: [PATCH 41/59] Add CollisionMatrix and CollisionFlag. --- src/org/apollo/game/model/area/Sector.java | 68 ++++-- .../model/area/collision/CollisionFlag.java | 100 ++++++++ .../model/area/collision/CollisionMatrix.java | 227 ++++++++++++++++++ .../model/area/collision/package-info.java | 4 + 4 files changed, 378 insertions(+), 21 deletions(-) create mode 100644 src/org/apollo/game/model/area/collision/CollisionFlag.java create mode 100644 src/org/apollo/game/model/area/collision/CollisionMatrix.java create mode 100644 src/org/apollo/game/model/area/collision/package-info.java diff --git a/src/org/apollo/game/model/area/Sector.java b/src/org/apollo/game/model/area/Sector.java index e1c35d46..3f582fe1 100644 --- a/src/org/apollo/game/model/area/Sector.java +++ b/src/org/apollo/game/model/area/Sector.java @@ -8,7 +8,9 @@ import java.util.Map; import java.util.Set; import java.util.stream.Collectors; +import org.apollo.game.model.Direction; import org.apollo.game.model.Position; +import org.apollo.game.model.area.collision.CollisionMatrix; import org.apollo.game.model.entity.Entity; import org.apollo.game.model.entity.Entity.EntityType; @@ -23,7 +25,7 @@ import com.google.common.collect.ImmutableSet; public final class Sector { /** - * The width and length of a sector, in tiles. + * The width and length of a Sector, in tiles. */ public static final int SECTOR_SIZE = 8; @@ -33,20 +35,25 @@ public final class Sector { private static final int DEFAULT_SET_SIZE = 2; /** - * The sector coordinates of this sector. + * The SectorCoordinates of this Sector. */ private final SectorCoordinates coordinates; /** - * A map of positions to entities in that position. + * The Map of Positions to Entities in that Position. */ private final Map> entities = new HashMap<>(); /** - * A list of listeners registered to this sector. + * A List of SectorListeners registered to this Sector. */ private final List listeners = new ArrayList<>(); + /** + * The CollisionMatrix. + */ + private final CollisionMatrix matrix = new CollisionMatrix(SECTOR_SIZE, SECTOR_SIZE); + /** * Creates a new sector. * @@ -67,28 +74,29 @@ public final class Sector { } /** - * Adds a {@link Entity} from to sector. Note that this does not spawn the entity, or do any other action other than + * Adds a {@link Entity} from to sector. Note that this does not spawn the Entity, or do any other action other than * register it to this sector. * - * @param entity The entity. - * @throws IllegalArgumentException If the entity does not belong in this sector. + * @param entity The Entity. + * @throws IllegalArgumentException If the Entity does not belong in this sector. */ public void addEntity(Entity entity) { Position position = entity.getPosition(); checkPosition(position); - Set local = entities.computeIfAbsent(position, key -> new HashSet<>(DEFAULT_SET_SIZE)); + Set local = entities.computeIfAbsent(position, key -> new HashSet<>(DEFAULT_SET_SIZE)); local.add(entity); + notifyListeners(entity, SectorOperation.ADD); } /** - * Checks if this sector contains the specified entity. + * Checks if this sector contains the specified Entity. *

* This method operates in constant time. * - * @param entity The entity. - * @return {@code true} if this sector contains the entity, otherwise {@code false}. + * @param entity The Entity. + * @return {@code true} if this sector contains the Entity, otherwise {@code false}. */ public boolean contains(Entity entity) { Position position = entity.getPosition(); @@ -114,12 +122,13 @@ public final class Sector { * @return The list. */ public Set getEntities(Position position) { - return ImmutableSet.copyOf(entities.computeIfAbsent(position, key -> new HashSet<>(DEFAULT_SET_SIZE))); + Set set = entities.get(position); + return (set == null) ? ImmutableSet.of() : ImmutableSet.copyOf(set); } /** * Gets a shallow copy of the {@link Set} of {@link Entity}s with the specified {@link EntityType}. The returned - * type will be immutable. Type will be inferred from the call, so ensure that the entity type and the reference + * type will be immutable. Type will be inferred from the call, so ensure that the Entity type and the reference * correspond, or this method will fail at runtime. * * @param position The {@link Position} containing the entities. @@ -127,21 +136,24 @@ public final class Sector { * @return The set of entities. */ public Set getEntities(Position position, EntityType type) { - Set local = entities.computeIfAbsent(position, key -> new HashSet<>(DEFAULT_SET_SIZE)); + Set local = entities.get(position); + if (local == null) { + return ImmutableSet.of(); + } @SuppressWarnings("unchecked") - Set filtered = (Set) local.stream().filter(entity -> entity.getEntityType() == type).collect(Collectors.toSet()); + Set filtered = (Set) local.stream().filter(Entity -> Entity.getEntityType() == type).collect(Collectors.toSet()); return ImmutableSet.copyOf(filtered); } /** * Moves the {@link Entity} that was in the specified {@code old} {@link Position}, to the current position of the - * entity. + * Entity. *

- * Both the {@code old} and current positions of the entity must belong to this sector. + * Both the {@code old} and current positions of the Entity must belong to this sector. * - * @param old The old position of the entity. - * @param entity The entity to move. + * @param old The old position of the Entity. + * @param entity The Entity to move. * @throws IllegalArgumentException If either of the positions do not belong to this sector. */ public void moveEntity(Position old, Entity entity) { @@ -175,8 +187,8 @@ public final class Sector { /** * Removes a {@link Entity} from this sector. * - * @param entity The entity. - * @throws IllegalArgumentException If the entity does not belong in this sector, or if it was never added. + * @param entity The Entity. + * @throws IllegalArgumentException If the Entity does not belong in this sector, or if it was never added. */ public void removeEntity(Entity entity) { Position position = entity.getPosition(); @@ -191,6 +203,20 @@ public final class Sector { notifyListeners(entity, SectorOperation.REMOVE); } + /** + * Returns whether or not an Entity of the specified {@link EntityType type} can traverse the tile at the specified + * coordinate pair. + * + * @param x The x coordinate. + * @param y The y coordinate. + * @param entity The {@link EntityType}. + * @param direction The {@link Direction} the Entity is approaching from. + * @return {@code true} if the tile at the specified coordinate pair is traversable, {@code false} if not. + */ + public boolean traversable(int x, int y, EntityType entity, Direction direction) { + return matrix.traversable(x, y, entity, direction); + } + /** * Checks that the specified {@link Position} is included in this sector. * diff --git a/src/org/apollo/game/model/area/collision/CollisionFlag.java b/src/org/apollo/game/model/area/collision/CollisionFlag.java new file mode 100644 index 00000000..b129511b --- /dev/null +++ b/src/org/apollo/game/model/area/collision/CollisionFlag.java @@ -0,0 +1,100 @@ +package org.apollo.game.model.area.collision; + +/** + * A type of flag in a {@link CollisionMatrix}. + * + * @author Major + */ +public enum CollisionFlag { + + /** + * The walk north flag. + */ + MOB_NORTH(0), + + /** + * The walk east flag. + */ + MOB_EAST(1), + + /** + * The walk south flag. + */ + MOB_SOUTH(2), + + /** + * The walk west flag. + */ + MOB_WEST(3), + + /** + * The projectile north flag. + */ + PROJECTILE_NORTH(4), + + /** + * The projectile east flag. + */ + PROJECTILE_EAST(5), + + /** + * The projectile south flag. + */ + PROJECTILE_SOUTH(6), + + /** + * The projectile west flag. + */ + PROJECTILE_WEST(7); + + /** + * Returns an array of CollisionFlags that indicate if a Mob can traverse over a tile. + * + * @return The array of CollisionFlags. + */ + public static CollisionFlag[] mobs() { + return new CollisionFlag[] { MOB_NORTH, MOB_EAST, MOB_SOUTH, MOB_WEST }; + } + + /** + * Returns an array of CollisionFlags that indicate if a Projectile can traverse over a tile. + * + * @return The array of CollisionFlags. + */ + public static CollisionFlag[] projectiles() { + return new CollisionFlag[] { PROJECTILE_NORTH, PROJECTILE_EAST, PROJECTILE_SOUTH, PROJECTILE_WEST }; + } + + /** + * The index of the bit this flag is stored in. + */ + private final int bit; + + /** + * Creates the CollisionFlag. + * + * @param bit The index of the bit this flag is stored in. + */ + private CollisionFlag(int bit) { + this.bit = bit; + } + + /** + * Gets this CollisionFlag, as a {@code byte}. + * + * @return The value, as a {@code byte}. + */ + public byte asByte() { + return (byte) (1 << bit); + } + + /** + * Gets the index of the bit this flag is stored in. + * + * @return The index of the bit. + */ + public int getBit() { + return bit; + } + +} \ No newline at end of file diff --git a/src/org/apollo/game/model/area/collision/CollisionMatrix.java b/src/org/apollo/game/model/area/collision/CollisionMatrix.java new file mode 100644 index 00000000..6c370591 --- /dev/null +++ b/src/org/apollo/game/model/area/collision/CollisionMatrix.java @@ -0,0 +1,227 @@ +package org.apollo.game.model.area.collision; + +import java.util.Arrays; + +import org.apollo.game.model.Direction; +import org.apollo.game.model.entity.Entity.EntityType; + +import com.google.common.base.MoreObjects; +import com.google.common.base.Preconditions; + +/** + * A 2-dimensional adjacency matrix containing tile collision data. + * + * @author Major + */ +public final class CollisionMatrix { + + /** + * Indicates that all types of traversal are allowed. + */ + private static final byte ALL_ALLOWED = 0b0000_0000; + + /** + * Indicates that no types of traversal are allowed. + */ + private static final byte ALL_BLOCKED = (byte) 0b1111_1111; + + /** + * The length of the matrix. + */ + private final int length; + + /** + * The collision matrix, as a {@code byte} array. + */ + private final byte[] matrix; + + /** + * The width of the matrix. + */ + private final int width; + + /** + * Creates the CollisionMatrix. + * + * @param width The width of the matrix. + * @param length The length of the matrix. + */ + public CollisionMatrix(int width, int length) { + this.width = width; + this.length = length; + matrix = new byte[width * length]; + } + + /** + * Returns whether or not all of the specified {@link CollisionFlag}s are set for the specified + * coordinate pair. + * + * @param x The x coordinate. + * @param y The y coordinate. + * @param flags The CollisionFlags. + * @return {@code true} if all of the CollisionFlags are set, otherwise {@code false}. + */ + public boolean all(int x, int y, CollisionFlag... flags) { + for (CollisionFlag flag : flags) { + if ((get(x, y) & flag.asByte()) == 0) { + return false; + } + } + + return true; + } + + /** + * Returns whether or not any of the specified {@link CollisionFlag}s are set for the specified + * coordinate pair. + * + * @param x The x coordinate. + * @param y The y coordinate. + * @param flags The CollisionFlags. + * @return {@code true} if any of the CollisionFlags are set, otherwise {@code false}. + */ + public boolean any(int x, int y, CollisionFlag... flags) { + for (CollisionFlag flag : flags) { + if ((get(x, y) & flag.asByte()) != 0) { + return true; + } + } + + return false; + } + + /** + * Completely blocks the tile at the specified coordinate pair. + * + * @param x The x coordinate. + * @param y The y coordinate. + */ + public void block(int x, int y) { + set(x, y, ALL_BLOCKED); + } + + /** + * Clears (i.e. sets to {@code false}) the value of the specified {@link CollisionFlag} for the specified coordinate + * pair. + * + * @param x The x coordinate. + * @param y The y coordinate. + * @param flag The CollisionFlag. + */ + public void clear(int x, int y, CollisionFlag flag) { + set(x, y, (byte) ~flag.asByte()); + } + + /** + * Returns whether or not the specified {@link CollisionFlag} is set for the specified coordinate pair. + * + * @param x The x coordinate. + * @param y The y coordinate. + * @param flag The CollisionFlag. + * @return {@code true} if the CollisionFlag is set, {@code false} if not. + */ + public boolean flagged(int x, int y, CollisionFlag flag) { + return (get(x, y) & flag.asByte()) != 0; + } + + /** + * Gets the value of the specified tile. + * + * @param x The x coordinate of the tile. + * @param y The y coordinate of the tile. + * @return The value. + */ + public int get(int x, int y) { + return matrix[indexOf(x, y)] & 0xFF; + } + + /** + * Resets the cell of the specified coordinate pair. + * + * @param x The x coordinate. + * @param y The y coordinate. + */ + public void reset(int x, int y) { + set(x, y, ALL_ALLOWED); + } + + /** + * Sets (i.e. sets to {@code true}) the value of the specified {@link CollisionFlag} for the specified coordinate + * pair. + * + * @param x The x coordinate. + * @param y The y coordinate. + * @param flag The CollisionFlag. + */ + public void set(int x, int y, CollisionFlag flag) { + set(x, y, flag.asByte()); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this).add("width", width).add("length", length).add("matrix", Arrays.toString(matrix)) + .toString(); + } + + /** + * Returns whether or not an Entity of the specified {@link EntityType type} can traverse the tile at the specified + * coordinate pair. + * + * @param x The x coordinate. + * @param y The y coordinate. + * @param entity The {@link EntityType}. + * @param direction The {@link Direction} the Entity is approaching from. + * @return {@code true} if the tile at the specified coordinate pair is traversable, {@code false} if not. + */ + public boolean traversable(int x, int y, EntityType entity, Direction direction) { + CollisionFlag[] flags = (entity == EntityType.PROJECTILE) ? CollisionFlag.projectiles() : CollisionFlag.mobs(); + int north = 0, east = 1, south = 2, west = 3; + + switch (direction) { + case NORTH_WEST: + return any(x, y, flags[south], flags[east]); + case NORTH: + return flagged(x, y, flags[south]); + case NORTH_EAST: + return any(x, y, flags[south], flags[west]); + case EAST: + return flagged(x, y, flags[west]); + case SOUTH_EAST: + return any(x, y, flags[north], flags[west]); + case SOUTH: + return flagged(x, y, flags[north]); + case SOUTH_WEST: + return any(x, y, flags[north], flags[east]); + case WEST: + return flagged(x, y, flags[east]); + } + + throw new IllegalArgumentException("Unrecognised direction " + direction + "."); + } + + /** + * Gets the index in the matrix for the specified coordinate pair. + * + * @param x The x coordinate. + * @param y The y coordinate. + * @return The index. + * @throws ArrayIndexOutOfBoundsException If the specified coordinate pair does not fit in this matrix. + */ + private int indexOf(int x, int y) { + int index = y * width + x; + Preconditions.checkElementIndex(index, matrix.length, "Index out of bounds."); + return index; + } + + /** + * Sets the appropriate index for the specified coordinate pair to the specified value. + * + * @param x The x coordinate. + * @param y The y coordinate. + * @param value The value. + */ + private void set(int x, int y, byte value) { + matrix[indexOf(x, y)] = value; + } + +} \ No newline at end of file diff --git a/src/org/apollo/game/model/area/collision/package-info.java b/src/org/apollo/game/model/area/collision/package-info.java new file mode 100644 index 00000000..aeb5e04c --- /dev/null +++ b/src/org/apollo/game/model/area/collision/package-info.java @@ -0,0 +1,4 @@ +/** + * Contains classes related to tile collision data. + */ +package org.apollo.game.model.area.collision; \ No newline at end of file From 30deffa7bcf2b5111fc350c9d83d4b44c261e65e Mon Sep 17 00:00:00 2001 From: Major- Date: Sat, 28 Feb 2015 05:32:15 +0000 Subject: [PATCH 42/59] Use Mob instead of Entity in attributes.rb. --- data/plugins/entity/attributes/attributes.rb | 30 ++++++++++++-------- 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/data/plugins/entity/attributes/attributes.rb b/data/plugins/entity/attributes/attributes.rb index 5deaa889..75183026 100644 --- a/data/plugins/entity/attributes/attributes.rb +++ b/data/plugins/entity/attributes/attributes.rb @@ -1,6 +1,8 @@ require 'java' -java_import 'org.apollo.game.model.entity.Entity' +java_import 'org.apollo.game.model.entity.Mob' +java_import 'org.apollo.game.model.entity.Npc' +java_import 'org.apollo.game.model.entity.Player' java_import 'org.apollo.game.model.entity.attr.Attribute' java_import 'org.apollo.game.model.entity.attr.AttributeDefinition' java_import 'org.apollo.game.model.entity.attr.AttributeMap' @@ -10,7 +12,18 @@ java_import 'org.apollo.game.model.entity.attr.BooleanAttribute' java_import 'org.apollo.game.model.entity.attr.NumericalAttribute' java_import 'org.apollo.game.model.entity.attr.StringAttribute' -class Entity + +# Declares an attribute and adds its definition. +def declare_attribute(name, default, persistence=:transient) + raise "Attribute #{name} clashes with an existing variable." if (Player.method_defined?(name) || Mob.method_defined?(name) || Npc.method_defined?(name)) + AttributeMap::add_definition(name.to_s, AttributeDefinition.new(default, get_persistence(persistence), get_type(default))) +end + + +private + +# The existing Mob class. +class Mob # Overrides method_missing def method_missing(symbol, *args) @@ -27,12 +40,11 @@ class Entity attribute = get_attribute(name); definition = AttributeMap::get_definition(name) value = attribute.nil? ? definition.default : attribute.value - return definition.type == AttributeType::SYMBOL ? value.to_sym : value + return (definition.type == AttributeType::SYMBOL) ? value.to_sym : value end end # Gets the appropriate attribute for the specified value. - private def to_attribute(value) case value when String, Symbol then return StringAttribute.new(value.to_s, value.is_a?(Symbol)) @@ -44,13 +56,7 @@ class Entity end -# Declares an attribute and adds its definition. -def declare_attribute(name, default, persistence=:transient) - AttributeMap::add_definition(name.to_s, AttributeDefinition.new(default, get_persistence(persistence), get_type(default))) -end - # Gets the attribute type of the specified value. -private def get_type(value) case value when String then return AttributeType::STRING @@ -64,7 +70,7 @@ end # Gets the Persistence type of the specified value. def get_persistence(persistence) - raise "Undefined persistence type #{persistence}." unless persistence == :persistent || persistence == :transient + raise "Undefined persistence type #{persistence}." unless [ :persistent, :transient ].include?(persistence) - return persistence == :persistent ? AttributePersistence::SERIALIZED : AttributePersistence::TRANSIENT + return (persistence == :persistent) ? AttributePersistence::SERIALIZED : AttributePersistence::TRANSIENT end \ No newline at end of file From 6d0b832bfd97232ad195b62f21b8a113a3a7de12 Mon Sep 17 00:00:00 2001 From: Major- Date: Sat, 28 Feb 2015 09:45:44 +0000 Subject: [PATCH 43/59] Remove statement dialogue type, automatically infer that type if no continue option is specified. --- data/plugins/dialogue/dialogue.rb | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/data/plugins/dialogue/dialogue.rb b/data/plugins/dialogue/dialogue.rb index 8c954c0e..ffe51c9a 100644 --- a/data/plugins/dialogue/dialogue.rb +++ b/data/plugins/dialogue/dialogue.rb @@ -41,14 +41,13 @@ class Conversation raise "Conversations #{@name} already has a dialogue named #{name}." if @dialogues.has_key?(name) @dialogues[name] = dialogue - if ((@dialogues.empty? || dialogue.has_precondition) && dialogue.type == :npc_speech) + if ((@dialogues.empty? || dialogue.has_precondition?) && dialogue.type == :npc_speech) npc = dialogue.npc raise 'Npc cannot be null when opening a dialogue.' if npc.nil? @starters << dialogue on :message, :first_npc_action do |ctx, player, event| - id = $world.npc_repository.get(event.index).id - if npc == id + if npc == $world.npc_repository.get(event.index).id @starters.each do |start| if dialogue.precondition(player) send_dialogue(player, dialogue) @@ -87,8 +86,8 @@ def send_dialogue(player, dialogue) when :npc_speech then send_npc_dialogue(player, dialogue) when :options then send_options_dialogue(player, dialogue) when :player_speech then send_player_dialogue(player, dialogue) - when :text then send_text_dialogue(player, dialogue) - when :statement then send_statement_dialogue(player, dialogue) + when :text + if dialogue.has_continue? then send_text_dialogue(player, dialogue) else send_statement_dialogue(player, dialogue) end else raise "Unrecognised dialogue type #{type}." end end @@ -111,7 +110,7 @@ MAXIMUM_MEDIA_LINE_WIDTH = 350 MAXIMUM_LINE_WIDTH = 430 # The possible types of a dialogue. -DIALOGUE_TYPES = [ :message_with_item, :message_with_model, :npc_speech, :options, :player_speech, :statement, :text ] +DIALOGUE_TYPES = [ :message_with_item, :message_with_model, :npc_speech, :options, :player_speech, :text ] # A type of dialogue. class Dialogue @@ -166,8 +165,13 @@ class Dialogue @emote end + # Returns whether or not this Dialogue has a continue option. + def has_continue? + !@options.empty? + end + # Returns whether or not this dialogue has a precondition. - def has_precondition + def has_precondition? !@precondition.nil? end @@ -254,10 +258,10 @@ class Dialogue end # Wraps text in this Dialogue, inserting extra Dialogues in the chain if necessary. - def wrap + def wrap # TODO redo this next if @type == :options lines = [] - maximum_width = [ :text, :statement ].include?(@type) ? MAXIMUM_LINE_WIDTH : MAXIMUM_MEDIA_LINE_WIDTH + maximum_width = (@type == :text) ? MAXIMUM_LINE_WIDTH : MAXIMUM_MEDIA_LINE_WIDTH maximum_lines = MAXIMUM_LINE_COUNT text = @text.first @@ -311,12 +315,12 @@ class Dialogue end # Decodes the next dialogue interface from the hash, returning a proc. - def get_next_dialogue(hash) - hash.keys.each do |key| + def get_next_dialogue(hash) # TODO rename + hash.each_pair do |key, value| case key when :disabled then return ->(player) { } when :close then return ->(player) { player.send(CloseInterfaceMessage.new) } - when :dialogue then return ->(player) { send_dialogue(player, @conversation.part(hash[key])) } + when :dialogue then return ->(player) { send_dialogue(player, @conversation.part(value)) } else raise "Unrecognised dialogue continue type #{key}." end end From 603f76d2c26e9881706c445189af9eca2db31acf Mon Sep 17 00:00:00 2001 From: Major- Date: Sat, 28 Feb 2015 11:59:00 +0000 Subject: [PATCH 44/59] Add PlayerPositionUpdateEvent. --- src/org/apollo/game/model/entity/Mob.java | 2 +- src/org/apollo/game/model/entity/Player.java | 7 ++++++ .../event/impl/PlayerPositionUpdateEvent.java | 22 +++++++++++++++++++ 3 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 src/org/apollo/game/model/event/impl/PlayerPositionUpdateEvent.java diff --git a/src/org/apollo/game/model/entity/Mob.java b/src/org/apollo/game/model/entity/Mob.java index 8bdf5f6f..26d847fa 100644 --- a/src/org/apollo/game/model/entity/Mob.java +++ b/src/org/apollo/game/model/entity/Mob.java @@ -427,7 +427,7 @@ public abstract class Mob extends Entity { * * @param position The position. */ - public final void setPosition(Position position) { + public void setPosition(Position position) { Position old = this.position; SectorRepository repository = World.getWorld().getSectorRepository(); Sector current = repository.fromPosition(old); diff --git a/src/org/apollo/game/model/entity/Player.java b/src/org/apollo/game/model/entity/Player.java index 578dfecd..d12c182e 100644 --- a/src/org/apollo/game/model/entity/Player.java +++ b/src/org/apollo/game/model/entity/Player.java @@ -21,6 +21,7 @@ import org.apollo.game.model.World; import org.apollo.game.model.area.Sector; import org.apollo.game.model.event.impl.LoginEvent; import org.apollo.game.model.event.impl.LogoutEvent; +import org.apollo.game.model.event.impl.PlayerPositionUpdateEvent; import org.apollo.game.model.inter.InterfaceConstants; import org.apollo.game.model.inter.InterfaceListener; import org.apollo.game.model.inter.InterfaceSet; @@ -717,6 +718,12 @@ public final class Player extends Mob { sendMessage(message, false); } + @Override + public void setPosition(Position position) { + super.setPosition(position); + World.getWorld().submit(new PlayerPositionUpdateEvent(this)); + } + /** * Sends a message to the player. * diff --git a/src/org/apollo/game/model/event/impl/PlayerPositionUpdateEvent.java b/src/org/apollo/game/model/event/impl/PlayerPositionUpdateEvent.java new file mode 100644 index 00000000..2681b00f --- /dev/null +++ b/src/org/apollo/game/model/event/impl/PlayerPositionUpdateEvent.java @@ -0,0 +1,22 @@ +package org.apollo.game.model.event.impl; + +import org.apollo.game.model.entity.Player; +import org.apollo.game.model.event.PlayerEvent; + +/** + * A {@link PlayerEvent} created when a Player's Position is being updated. + * + * @author Major + */ +public final class PlayerPositionUpdateEvent extends PlayerEvent { + + /** + * Creates the PlayerPositionUpdateEvent. + * + * @param player The {@link Player} whose Position is being updated. + */ + public PlayerPositionUpdateEvent(Player player) { + super(player); + } + +} \ No newline at end of file From f528987019cb02cb8a7d04df5996c590f7dfdb1a Mon Sep 17 00:00:00 2001 From: Major- Date: Sat, 28 Feb 2015 12:42:16 +0000 Subject: [PATCH 45/59] Change PlayerPositionUpdateEvent to MobPositionUpdateEvent. --- src/org/apollo/game/model/entity/Mob.java | 8 ++- src/org/apollo/game/model/entity/Player.java | 7 --- .../event/impl/MobPositionUpdateEvent.java | 56 +++++++++++++++++++ .../event/impl/PlayerPositionUpdateEvent.java | 22 -------- 4 files changed, 62 insertions(+), 31 deletions(-) create mode 100644 src/org/apollo/game/model/event/impl/MobPositionUpdateEvent.java delete mode 100644 src/org/apollo/game/model/event/impl/PlayerPositionUpdateEvent.java diff --git a/src/org/apollo/game/model/entity/Mob.java b/src/org/apollo/game/model/entity/Mob.java index 26d847fa..17c4f8ca 100644 --- a/src/org/apollo/game/model/entity/Mob.java +++ b/src/org/apollo/game/model/entity/Mob.java @@ -16,6 +16,7 @@ import org.apollo.game.model.area.SectorRepository; import org.apollo.game.model.def.NpcDefinition; import org.apollo.game.model.entity.attr.Attribute; import org.apollo.game.model.entity.attr.AttributeMap; +import org.apollo.game.model.event.impl.MobPositionUpdateEvent; import org.apollo.game.model.inv.Inventory; import org.apollo.game.model.inv.Inventory.StackMode; import org.apollo.game.model.inv.InventoryConstants; @@ -402,7 +403,7 @@ public abstract class Mob extends Entity { this.index = index; } } - + /** * Returns this mobs interacting index. * @@ -427,7 +428,10 @@ public abstract class Mob extends Entity { * * @param position The position. */ - public void setPosition(Position position) { + public final void setPosition(Position position) { + World.getWorld().submit(new MobPositionUpdateEvent(this, position)); + // Intentionally ignore the Event result - accidentally terminating this method would break the entire server. + Position old = this.position; SectorRepository repository = World.getWorld().getSectorRepository(); Sector current = repository.fromPosition(old); diff --git a/src/org/apollo/game/model/entity/Player.java b/src/org/apollo/game/model/entity/Player.java index d12c182e..578dfecd 100644 --- a/src/org/apollo/game/model/entity/Player.java +++ b/src/org/apollo/game/model/entity/Player.java @@ -21,7 +21,6 @@ import org.apollo.game.model.World; import org.apollo.game.model.area.Sector; import org.apollo.game.model.event.impl.LoginEvent; import org.apollo.game.model.event.impl.LogoutEvent; -import org.apollo.game.model.event.impl.PlayerPositionUpdateEvent; import org.apollo.game.model.inter.InterfaceConstants; import org.apollo.game.model.inter.InterfaceListener; import org.apollo.game.model.inter.InterfaceSet; @@ -718,12 +717,6 @@ public final class Player extends Mob { sendMessage(message, false); } - @Override - public void setPosition(Position position) { - super.setPosition(position); - World.getWorld().submit(new PlayerPositionUpdateEvent(this)); - } - /** * Sends a message to the player. * diff --git a/src/org/apollo/game/model/event/impl/MobPositionUpdateEvent.java b/src/org/apollo/game/model/event/impl/MobPositionUpdateEvent.java new file mode 100644 index 00000000..82f9a470 --- /dev/null +++ b/src/org/apollo/game/model/event/impl/MobPositionUpdateEvent.java @@ -0,0 +1,56 @@ +package org.apollo.game.model.event.impl; + +import org.apollo.game.model.Position; +import org.apollo.game.model.entity.Mob; +import org.apollo.game.model.event.Event; + +/** + * An {@link Event} created when a Mob's Position is being updated. + *

+ * This Event intentionally ignores the result of execution - it should not be possible for a plugin to prevent this + * Event from happening, only to listen for it. + * + * @author Major + */ +public final class MobPositionUpdateEvent extends Event { + + /** + * The Mob whose position is being updated. + */ + private final Mob mob; + + /** + * The next Position of the Mob. + */ + private final Position next; + + /** + * Creates the MobPositionUpdateEvent. + * + * @param mob The {@link Mob} whose Position is being updated. + * @param next The next {@link Position} of the Mob. + */ + public MobPositionUpdateEvent(Mob mob, Position next) { + this.mob = mob; + this.next = next; + } + + /** + * Gets the {@link Mob} being moved. + * + * @return The Mob. + */ + public Mob getMob() { + return mob; + } + + /** + * Gets the {@link Position} this {@link Mob} is being moved to. + * + * @return The Position. + */ + public Position getNext() { + return next; + } + +} \ No newline at end of file diff --git a/src/org/apollo/game/model/event/impl/PlayerPositionUpdateEvent.java b/src/org/apollo/game/model/event/impl/PlayerPositionUpdateEvent.java deleted file mode 100644 index 2681b00f..00000000 --- a/src/org/apollo/game/model/event/impl/PlayerPositionUpdateEvent.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.apollo.game.model.event.impl; - -import org.apollo.game.model.entity.Player; -import org.apollo.game.model.event.PlayerEvent; - -/** - * A {@link PlayerEvent} created when a Player's Position is being updated. - * - * @author Major - */ -public final class PlayerPositionUpdateEvent extends PlayerEvent { - - /** - * Creates the PlayerPositionUpdateEvent. - * - * @param player The {@link Player} whose Position is being updated. - */ - public PlayerPositionUpdateEvent(Player player) { - super(player); - } - -} \ No newline at end of file From 3982c3b5f841a0e87696d25ba393d13808a805f8 Mon Sep 17 00:00:00 2001 From: Major- Date: Sun, 1 Mar 2015 02:31:05 +0000 Subject: [PATCH 46/59] Correct opcode of the 377 OpenDialogueOverlayMessage. --- .../net/release/r377/OpenDialogueOverlayMessageEncoder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/org/apollo/net/release/r377/OpenDialogueOverlayMessageEncoder.java b/src/org/apollo/net/release/r377/OpenDialogueOverlayMessageEncoder.java index 1f7f3ea6..aff73005 100644 --- a/src/org/apollo/net/release/r377/OpenDialogueOverlayMessageEncoder.java +++ b/src/org/apollo/net/release/r377/OpenDialogueOverlayMessageEncoder.java @@ -16,7 +16,7 @@ public final class OpenDialogueOverlayMessageEncoder extends MessageEncoder Date: Sun, 1 Mar 2015 02:31:55 +0000 Subject: [PATCH 47/59] Listen for the PositionUpdateEvent so area listeners now function. --- data/plugins/areas/actions.rb | 39 +++++----------- data/plugins/areas/areas.rb | 86 ++++++++++++++++++++++++++++------- 2 files changed, 82 insertions(+), 43 deletions(-) diff --git a/data/plugins/areas/actions.rb b/data/plugins/areas/actions.rb index e72f42f4..58eab91e 100644 --- a/data/plugins/areas/actions.rb +++ b/data/plugins/areas/actions.rb @@ -3,8 +3,20 @@ require 'java' java_import 'org.apollo.game.message.impl.DisplayCrossbonesMessage' java_import 'org.apollo.game.model.entity.Player' + + +# Registers an area action. +def area_action(name, &block) + AREA_ACTIONS[name] = action = AreaAction.new + action.instance_eval(&block) +end + + AREA_ACTIONS = {} + +private + # An action that is called when a player enters or exits an area. class AreaAction @@ -38,31 +50,4 @@ class AreaAction @on_exit.call(player) unless @on_exit.nil? end -end - -# Registers an area action. -def area_action(name, &block) - AREA_ACTIONS[name] = action = AreaAction.new - action.instance_eval(&block) -end - -# Defines the pvp area action. -area_action :pvp do - on_entry { |player| player.in_pvp = true } - on_exit { |player| player.in_pvp = false } -end - -# Defines the wilderness area action. -area_action :wilderness do - - on_entry do |player| - player.send(DisplayCrossbonesMessage.new(true)) - player.in_wilderness = true - end - - on_exit do |player| - player.send(DisplayCrossbonesMessage.new(false)) - player.in_wilderness = false - end - end \ No newline at end of file diff --git a/data/plugins/areas/areas.rb b/data/plugins/areas/areas.rb index cb540224..369dd2b7 100644 --- a/data/plugins/areas/areas.rb +++ b/data/plugins/areas/areas.rb @@ -1,11 +1,26 @@ require 'java' +java_import 'org.apollo.game.model.Position' +java_import 'org.apollo.game.model.entity.Entity$EntityType' java_import 'org.apollo.game.model.entity.Player' -# Todo make 0 the default height + + +# Creates a new area and registers it with the supplied coordinates. +def area(hash) + raise 'Hash must contain a name, coordinates, and actions pair.' unless hash.has_keys?(:name, :coordinates, :actions) + name = hash[:name]; coordinates = hash[:coordinates]; actions = hash[:actions] + + actions = [ actions ] if actions.is_a?(Symbol) + actions.map! { |action| AREA_ACTIONS[action]} + @areas << Area.new(name, coordinates, actions) +end + + +private # A map of coordinates (as an array) to areas. -AREAS = [] +@areas = [] # An area of the game world. class Area @@ -16,31 +31,70 @@ class Area @actions = actions end - # Called when the player has entered the area. - def entered(player) - actions.each { |action| action.entered(player) } + def min_x() # TODO better data structure and methods than this + @coordinates[0] end - # Called whilst the player is inside the area. + def min_y() + @coordinates[1] + end + + def max_x() + @coordinates[2] + end + + def max_y() + @coordinates[3] + end + + def height() + @coordinates[4] + end + + # Called when the player has entered the area. + def entered(player) + @actions.each { |action| action.entered(player) } + end + + # Called when the player has moved, but is still inside the area (and was in the area before). def inside(player) - acttions.each { |action| action.inside(player) } + @actions.each { |action| action.inside(player) } end # Called when the player has exited the area. def exited(player) - actions.each { |action| action.exited(player) } + @actions.each { |action| action.exited(player) } end end -# Creates a new area and registers it with the supplied coordinates. -def area(hash) - raise 'Hash must contain a name, coordinates, and actions pair.' unless hash.has_keys?(:name, :coordinates, :actions) - name = hash[:name]; coordinates = hash[:coordinates]; actions = hash[:actions] +# Listen for the MobPositionUpdateEvent and update the area listeners if appropriate. +on :mob_position_update do |event| + mob = event.mob + next unless mob.entity_type == EntityType::PLAYER - AREAS << Area.new(name, coordinates, actions.is_a?(Symbol) ? [actions] : actions) + old = mob.position + @areas.each do |area| + was_inside = old.inside(area) + next_inside = event.next.inside(area) + + if was_inside + if next_inside then area.inside(mob) else area.exited(mob) end + else + area.entered(mob) if next_inside + end + end end -# Coordinates refer to the bottom-left position (min_x, min_y) and the top-right position (max_x, max_y), followed by the height (optional). -area :name => :wilderness, :coordinates => [ 2944, 3520, 3392, 6400, 0 ], :actions => [ :pvp, :multicombat, :wilderness ] -area :name => :duel_arena, :coordinates => [ 3327, 3200, 3392, 3286 ], :actions => :pvp \ No newline at end of file +# The existing Position class. +class Position + + # Returns whether or not this Position is inside the specified Area. + def inside(area) + return false if (x < area.min_x() || x > area.max_x() || y < area.min_y() || y > area.max_y()) + z = area.height() + + return true if (z.nil? || z == height) + end + +end \ No newline at end of file From 785e3a82aa3aa0d8a97da2bc392ff3ec969178a1 Mon Sep 17 00:00:00 2001 From: Major- Date: Sun, 1 Mar 2015 06:02:35 +0000 Subject: [PATCH 48/59] Don't send the initial events if the player is reconnecting. --- src/org/apollo/net/session/LoginSession.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/org/apollo/net/session/LoginSession.java b/src/org/apollo/net/session/LoginSession.java index 4f2b160d..0dfb07db 100644 --- a/src/org/apollo/net/session/LoginSession.java +++ b/src/org/apollo/net/session/LoginSession.java @@ -131,7 +131,7 @@ public final class LoginSession extends Session { future.addListener(ChannelFutureListener.CLOSE); } - if (optional.isPresent()) { + if (optional.isPresent() && request.isReconnecting()) { optional.get().sendInitialMessages(); } } From 8968786c018125b9472d4933a929ec05897d4140 Mon Sep 17 00:00:00 2001 From: Major- Date: Sun, 1 Mar 2015 08:46:55 +0000 Subject: [PATCH 49/59] Move 'org.apollo.game.model.setting' to 'org.apollo.game.model.entity.setting'. --- data/plugins/bootstrap.rb | 2 +- data/plugins/chat/privacy/privacy.rb | 2 +- data/plugins/chat/private-messaging/friend.rb | 4 ++-- data/plugins/chat/private-messaging/messaging.rb | 6 +++--- src/org/apollo/game/command/CommandListener.java | 2 +- .../handler/impl/PlayerDesignVerificationHandler.java | 2 +- .../game/message/impl/ForwardPrivateChatMessage.java | 2 +- .../game/message/impl/FriendServerStatusMessage.java | 2 +- .../apollo/game/message/impl/PrivacyOptionMessage.java | 2 +- src/org/apollo/game/model/Appearance.java | 2 +- src/org/apollo/game/model/entity/Player.java | 6 +++--- .../apollo/game/model/{ => entity}/setting/Gender.java | 2 +- .../game/model/{ => entity}/setting/PrivacyState.java | 2 +- .../game/model/{ => entity}/setting/PrivilegeLevel.java | 2 +- .../game/model/{ => entity}/setting/ScreenBrightness.java | 2 +- .../game/model/{ => entity}/setting/ServerStatus.java | 2 +- .../game/model/{ => entity}/setting/package-info.java | 2 +- src/org/apollo/game/sync/block/ChatBlock.java | 2 +- src/org/apollo/io/player/impl/BinaryPlayerLoader.java | 8 ++++---- src/org/apollo/io/player/impl/DummyPlayerLoader.java | 2 +- .../net/release/r317/PlayerDesignMessageDecoder.java | 2 +- .../release/r317/PlayerSynchronizationMessageEncoder.java | 2 +- .../net/release/r377/PlayerDesignMessageDecoder.java | 2 +- .../release/r377/PlayerSynchronizationMessageEncoder.java | 2 +- 24 files changed, 32 insertions(+), 32 deletions(-) rename src/org/apollo/game/model/{ => entity}/setting/Gender.java (91%) rename src/org/apollo/game/model/{ => entity}/setting/PrivacyState.java (98%) rename src/org/apollo/game/model/{ => entity}/setting/PrivilegeLevel.java (96%) rename src/org/apollo/game/model/{ => entity}/setting/ScreenBrightness.java (96%) rename src/org/apollo/game/model/{ => entity}/setting/ServerStatus.java (95%) rename src/org/apollo/game/model/{ => entity}/setting/package-info.java (60%) diff --git a/data/plugins/bootstrap.rb b/data/plugins/bootstrap.rb index 6d759fa2..134e006b 100644 --- a/data/plugins/bootstrap.rb +++ b/data/plugins/bootstrap.rb @@ -20,7 +20,7 @@ java_import 'org.apollo.game.model.World' java_import 'org.apollo.game.model.entity.Player' java_import 'org.apollo.game.model.event.EventListener' java_import 'org.apollo.game.model.event.PlayerEvent' -java_import 'org.apollo.game.model.setting.PrivilegeLevel' +java_import 'org.apollo.game.model.entity.setting.PrivilegeLevel' java_import 'org.apollo.game.scheduling.ScheduledTask' java_import 'org.apollo.util.plugin.PluginContext' diff --git a/data/plugins/chat/privacy/privacy.rb b/data/plugins/chat/privacy/privacy.rb index 4de03b8b..8200fce7 100644 --- a/data/plugins/chat/privacy/privacy.rb +++ b/data/plugins/chat/privacy/privacy.rb @@ -1,6 +1,6 @@ require 'java' -java_import 'org.apollo.game.model.setting.PrivacyState' +java_import 'org.apollo.game.model.entity.setting.PrivacyState' java_import 'org.apollo.game.message.impl.SendFriendMessage' on :message, :privacy_option do |ctx, player, message| diff --git a/data/plugins/chat/private-messaging/friend.rb b/data/plugins/chat/private-messaging/friend.rb index 6d1085e6..9433659a 100644 --- a/data/plugins/chat/private-messaging/friend.rb +++ b/data/plugins/chat/private-messaging/friend.rb @@ -4,8 +4,8 @@ java_import 'org.apollo.game.message.impl.FriendServerStatusMessage' java_import 'org.apollo.game.message.impl.IgnoreListMessage' java_import 'org.apollo.game.message.impl.SendFriendMessage' java_import 'org.apollo.game.model.World' -java_import 'org.apollo.game.model.setting.ServerStatus' -java_import 'org.apollo.game.model.setting.PrivacyState' +java_import 'org.apollo.game.model.entity.setting.ServerStatus' +java_import 'org.apollo.game.model.entity.setting.PrivacyState' java_import 'org.apollo.game.model.entity.Player' diff --git a/data/plugins/chat/private-messaging/messaging.rb b/data/plugins/chat/private-messaging/messaging.rb index 1d91b94d..17aa7d77 100644 --- a/data/plugins/chat/private-messaging/messaging.rb +++ b/data/plugins/chat/private-messaging/messaging.rb @@ -2,7 +2,7 @@ require 'java' java_import 'org.apollo.game.message.impl.ForwardPrivateChatMessage' java_import 'org.apollo.game.model.World' -java_import 'org.apollo.game.model.setting.PrivacyState' +java_import 'org.apollo.game.model.entity.setting.PrivacyState' on :message, :private_chat do |ctx, player, message| friend = $world.get_player(message.username) @@ -11,9 +11,9 @@ end # Checks if the sender is permitted to interact with the friend they have added: def interaction_permitted(sender, friend) - if friend == nil || friend.has_ignored(sender.username) + if friend.nil? || friend.has_ignored(sender.username) return false end - return friend.friends_with(sender.username) ? friend.friend_privacy != PrivacyState::OFF : friend.friend_privacy == PrivacyState::ON + return friend.friends_with(sender.username) ? (friend.friend_privacy != PrivacyState::OFF) : (friend.friend_privacy == PrivacyState::ON) end \ No newline at end of file diff --git a/src/org/apollo/game/command/CommandListener.java b/src/org/apollo/game/command/CommandListener.java index 57eeffe6..97202fa1 100644 --- a/src/org/apollo/game/command/CommandListener.java +++ b/src/org/apollo/game/command/CommandListener.java @@ -1,7 +1,7 @@ package org.apollo.game.command; import org.apollo.game.model.entity.Player; -import org.apollo.game.model.setting.PrivilegeLevel; +import org.apollo.game.model.entity.setting.PrivilegeLevel; /** * An interface which should be implemented to listen to {@link Command}s. diff --git a/src/org/apollo/game/message/handler/impl/PlayerDesignVerificationHandler.java b/src/org/apollo/game/message/handler/impl/PlayerDesignVerificationHandler.java index e0980b66..d09a5669 100644 --- a/src/org/apollo/game/message/handler/impl/PlayerDesignVerificationHandler.java +++ b/src/org/apollo/game/message/handler/impl/PlayerDesignVerificationHandler.java @@ -5,7 +5,7 @@ import org.apollo.game.message.handler.MessageHandlerContext; import org.apollo.game.message.impl.PlayerDesignMessage; import org.apollo.game.model.Appearance; import org.apollo.game.model.entity.Player; -import org.apollo.game.model.setting.Gender; +import org.apollo.game.model.entity.setting.Gender; /** * A {@link MessageHandler} that verifies {@link PlayerDesignMessage}s. diff --git a/src/org/apollo/game/message/impl/ForwardPrivateChatMessage.java b/src/org/apollo/game/message/impl/ForwardPrivateChatMessage.java index 10b7249f..b31d5397 100644 --- a/src/org/apollo/game/message/impl/ForwardPrivateChatMessage.java +++ b/src/org/apollo/game/message/impl/ForwardPrivateChatMessage.java @@ -1,7 +1,7 @@ package org.apollo.game.message.impl; import org.apollo.game.message.Message; -import org.apollo.game.model.setting.PrivilegeLevel; +import org.apollo.game.model.entity.setting.PrivilegeLevel; /** * A {@link Message} sent to the client that forwards a private chat. diff --git a/src/org/apollo/game/message/impl/FriendServerStatusMessage.java b/src/org/apollo/game/message/impl/FriendServerStatusMessage.java index 6ed66bc9..4960b853 100644 --- a/src/org/apollo/game/message/impl/FriendServerStatusMessage.java +++ b/src/org/apollo/game/message/impl/FriendServerStatusMessage.java @@ -1,7 +1,7 @@ package org.apollo.game.message.impl; import org.apollo.game.message.Message; -import org.apollo.game.model.setting.ServerStatus; +import org.apollo.game.model.entity.setting.ServerStatus; /** * A {@link Message} sent to the client to update the friend server status. diff --git a/src/org/apollo/game/message/impl/PrivacyOptionMessage.java b/src/org/apollo/game/message/impl/PrivacyOptionMessage.java index f53bde1f..c84f8812 100644 --- a/src/org/apollo/game/message/impl/PrivacyOptionMessage.java +++ b/src/org/apollo/game/message/impl/PrivacyOptionMessage.java @@ -1,7 +1,7 @@ package org.apollo.game.message.impl; import org.apollo.game.message.Message; -import org.apollo.game.model.setting.PrivacyState; +import org.apollo.game.model.entity.setting.PrivacyState; /** * A {@link Message} sent both by and to the client to update the public chat, private (friend) chat, and trade chat diff --git a/src/org/apollo/game/model/Appearance.java b/src/org/apollo/game/model/Appearance.java index 9a15b0ec..4ece0496 100644 --- a/src/org/apollo/game/model/Appearance.java +++ b/src/org/apollo/game/model/Appearance.java @@ -1,6 +1,6 @@ package org.apollo.game.model; -import org.apollo.game.model.setting.Gender; +import org.apollo.game.model.entity.setting.Gender; import com.google.common.base.Preconditions; diff --git a/src/org/apollo/game/model/entity/Player.java b/src/org/apollo/game/model/entity/Player.java index 578dfecd..8b02a12b 100644 --- a/src/org/apollo/game/model/entity/Player.java +++ b/src/org/apollo/game/model/entity/Player.java @@ -19,6 +19,9 @@ import org.apollo.game.model.Appearance; import org.apollo.game.model.Position; import org.apollo.game.model.World; import org.apollo.game.model.area.Sector; +import org.apollo.game.model.entity.setting.PrivacyState; +import org.apollo.game.model.entity.setting.PrivilegeLevel; +import org.apollo.game.model.entity.setting.ScreenBrightness; import org.apollo.game.model.event.impl.LoginEvent; import org.apollo.game.model.event.impl.LogoutEvent; import org.apollo.game.model.inter.InterfaceConstants; @@ -33,9 +36,6 @@ import org.apollo.game.model.inv.Inventory.StackMode; import org.apollo.game.model.inv.InventoryConstants; import org.apollo.game.model.inv.InventoryListener; import org.apollo.game.model.inv.SynchronizationInventoryListener; -import org.apollo.game.model.setting.PrivacyState; -import org.apollo.game.model.setting.PrivilegeLevel; -import org.apollo.game.model.setting.ScreenBrightness; import org.apollo.game.model.skill.LevelUpSkillListener; import org.apollo.game.model.skill.SynchronizationSkillListener; import org.apollo.game.sync.block.SynchronizationBlock; diff --git a/src/org/apollo/game/model/setting/Gender.java b/src/org/apollo/game/model/entity/setting/Gender.java similarity index 91% rename from src/org/apollo/game/model/setting/Gender.java rename to src/org/apollo/game/model/entity/setting/Gender.java index 1e95bae1..9cd43668 100644 --- a/src/org/apollo/game/model/setting/Gender.java +++ b/src/org/apollo/game/model/entity/setting/Gender.java @@ -1,4 +1,4 @@ -package org.apollo.game.model.setting; +package org.apollo.game.model.entity.setting; /** * An enumeration containing the two genders (male and female). This enumeration relies on the ordering of the elements diff --git a/src/org/apollo/game/model/setting/PrivacyState.java b/src/org/apollo/game/model/entity/setting/PrivacyState.java similarity index 98% rename from src/org/apollo/game/model/setting/PrivacyState.java rename to src/org/apollo/game/model/entity/setting/PrivacyState.java index 0a62b1fc..76fbec8d 100644 --- a/src/org/apollo/game/model/setting/PrivacyState.java +++ b/src/org/apollo/game/model/entity/setting/PrivacyState.java @@ -1,4 +1,4 @@ -package org.apollo.game.model.setting; +package org.apollo.game.model.entity.setting; import com.google.common.base.Preconditions; diff --git a/src/org/apollo/game/model/setting/PrivilegeLevel.java b/src/org/apollo/game/model/entity/setting/PrivilegeLevel.java similarity index 96% rename from src/org/apollo/game/model/setting/PrivilegeLevel.java rename to src/org/apollo/game/model/entity/setting/PrivilegeLevel.java index e5738f7c..fbdaf7c6 100644 --- a/src/org/apollo/game/model/setting/PrivilegeLevel.java +++ b/src/org/apollo/game/model/entity/setting/PrivilegeLevel.java @@ -1,4 +1,4 @@ -package org.apollo.game.model.setting; +package org.apollo.game.model.entity.setting; import com.google.common.base.Preconditions; diff --git a/src/org/apollo/game/model/setting/ScreenBrightness.java b/src/org/apollo/game/model/entity/setting/ScreenBrightness.java similarity index 96% rename from src/org/apollo/game/model/setting/ScreenBrightness.java rename to src/org/apollo/game/model/entity/setting/ScreenBrightness.java index 9ae6cd9c..4a190a44 100644 --- a/src/org/apollo/game/model/setting/ScreenBrightness.java +++ b/src/org/apollo/game/model/entity/setting/ScreenBrightness.java @@ -1,4 +1,4 @@ -package org.apollo.game.model.setting; +package org.apollo.game.model.entity.setting; import com.google.common.base.Preconditions; diff --git a/src/org/apollo/game/model/setting/ServerStatus.java b/src/org/apollo/game/model/entity/setting/ServerStatus.java similarity index 95% rename from src/org/apollo/game/model/setting/ServerStatus.java rename to src/org/apollo/game/model/entity/setting/ServerStatus.java index 05bc3d8e..651d4b88 100644 --- a/src/org/apollo/game/model/setting/ServerStatus.java +++ b/src/org/apollo/game/model/entity/setting/ServerStatus.java @@ -1,4 +1,4 @@ -package org.apollo.game.model.setting; +package org.apollo.game.model.entity.setting; import com.google.common.base.Preconditions; diff --git a/src/org/apollo/game/model/setting/package-info.java b/src/org/apollo/game/model/entity/setting/package-info.java similarity index 60% rename from src/org/apollo/game/model/setting/package-info.java rename to src/org/apollo/game/model/entity/setting/package-info.java index 5c8ed99e..db35d20a 100644 --- a/src/org/apollo/game/model/setting/package-info.java +++ b/src/org/apollo/game/model/entity/setting/package-info.java @@ -1,4 +1,4 @@ /** * Contains player setting or customisation-related classes. */ -package org.apollo.game.model.setting; \ No newline at end of file +package org.apollo.game.model.entity.setting; \ No newline at end of file diff --git a/src/org/apollo/game/sync/block/ChatBlock.java b/src/org/apollo/game/sync/block/ChatBlock.java index de3eb001..14bbba81 100644 --- a/src/org/apollo/game/sync/block/ChatBlock.java +++ b/src/org/apollo/game/sync/block/ChatBlock.java @@ -1,7 +1,7 @@ package org.apollo.game.sync.block; import org.apollo.game.message.impl.ChatMessage; -import org.apollo.game.model.setting.PrivilegeLevel; +import org.apollo.game.model.entity.setting.PrivilegeLevel; /** * The chat {@link SynchronizationBlock}. Only players can utilise this block. diff --git a/src/org/apollo/io/player/impl/BinaryPlayerLoader.java b/src/org/apollo/io/player/impl/BinaryPlayerLoader.java index ada3d857..00d2fe89 100644 --- a/src/org/apollo/io/player/impl/BinaryPlayerLoader.java +++ b/src/org/apollo/io/player/impl/BinaryPlayerLoader.java @@ -20,11 +20,11 @@ import org.apollo.game.model.entity.attr.AttributeType; import org.apollo.game.model.entity.attr.BooleanAttribute; import org.apollo.game.model.entity.attr.NumericalAttribute; import org.apollo.game.model.entity.attr.StringAttribute; +import org.apollo.game.model.entity.setting.Gender; +import org.apollo.game.model.entity.setting.PrivacyState; +import org.apollo.game.model.entity.setting.PrivilegeLevel; +import org.apollo.game.model.entity.setting.ScreenBrightness; import org.apollo.game.model.inv.Inventory; -import org.apollo.game.model.setting.Gender; -import org.apollo.game.model.setting.PrivacyState; -import org.apollo.game.model.setting.PrivilegeLevel; -import org.apollo.game.model.setting.ScreenBrightness; import org.apollo.io.player.PlayerLoader; import org.apollo.io.player.PlayerLoaderResponse; import org.apollo.net.codec.login.LoginConstants; diff --git a/src/org/apollo/io/player/impl/DummyPlayerLoader.java b/src/org/apollo/io/player/impl/DummyPlayerLoader.java index 0cc48ed4..95cd971d 100644 --- a/src/org/apollo/io/player/impl/DummyPlayerLoader.java +++ b/src/org/apollo/io/player/impl/DummyPlayerLoader.java @@ -2,7 +2,7 @@ package org.apollo.io.player.impl; import org.apollo.game.model.Position; import org.apollo.game.model.entity.Player; -import org.apollo.game.model.setting.PrivilegeLevel; +import org.apollo.game.model.entity.setting.PrivilegeLevel; import org.apollo.io.player.PlayerLoader; import org.apollo.io.player.PlayerLoaderResponse; import org.apollo.net.codec.login.LoginConstants; diff --git a/src/org/apollo/net/release/r317/PlayerDesignMessageDecoder.java b/src/org/apollo/net/release/r317/PlayerDesignMessageDecoder.java index 9aaaaf51..52d684ef 100644 --- a/src/org/apollo/net/release/r317/PlayerDesignMessageDecoder.java +++ b/src/org/apollo/net/release/r317/PlayerDesignMessageDecoder.java @@ -2,7 +2,7 @@ package org.apollo.net.release.r317; import org.apollo.game.message.impl.PlayerDesignMessage; import org.apollo.game.model.Appearance; -import org.apollo.game.model.setting.Gender; +import org.apollo.game.model.entity.setting.Gender; import org.apollo.net.codec.game.DataType; import org.apollo.net.codec.game.GamePacket; import org.apollo.net.codec.game.GamePacketReader; diff --git a/src/org/apollo/net/release/r317/PlayerSynchronizationMessageEncoder.java b/src/org/apollo/net/release/r317/PlayerSynchronizationMessageEncoder.java index 5908d2e9..a1a55d14 100644 --- a/src/org/apollo/net/release/r317/PlayerSynchronizationMessageEncoder.java +++ b/src/org/apollo/net/release/r317/PlayerSynchronizationMessageEncoder.java @@ -9,8 +9,8 @@ import org.apollo.game.model.Item; import org.apollo.game.model.Position; import org.apollo.game.model.def.EquipmentDefinition; import org.apollo.game.model.entity.EquipmentConstants; +import org.apollo.game.model.entity.setting.Gender; import org.apollo.game.model.inv.Inventory; -import org.apollo.game.model.setting.Gender; import org.apollo.game.sync.block.AnimationBlock; import org.apollo.game.sync.block.AppearanceBlock; import org.apollo.game.sync.block.ChatBlock; diff --git a/src/org/apollo/net/release/r377/PlayerDesignMessageDecoder.java b/src/org/apollo/net/release/r377/PlayerDesignMessageDecoder.java index 0572398e..61593731 100644 --- a/src/org/apollo/net/release/r377/PlayerDesignMessageDecoder.java +++ b/src/org/apollo/net/release/r377/PlayerDesignMessageDecoder.java @@ -2,7 +2,7 @@ package org.apollo.net.release.r377; import org.apollo.game.message.impl.PlayerDesignMessage; import org.apollo.game.model.Appearance; -import org.apollo.game.model.setting.Gender; +import org.apollo.game.model.entity.setting.Gender; import org.apollo.net.codec.game.DataType; import org.apollo.net.codec.game.GamePacket; import org.apollo.net.codec.game.GamePacketReader; diff --git a/src/org/apollo/net/release/r377/PlayerSynchronizationMessageEncoder.java b/src/org/apollo/net/release/r377/PlayerSynchronizationMessageEncoder.java index cc68abd8..341a1b17 100644 --- a/src/org/apollo/net/release/r377/PlayerSynchronizationMessageEncoder.java +++ b/src/org/apollo/net/release/r377/PlayerSynchronizationMessageEncoder.java @@ -9,8 +9,8 @@ import org.apollo.game.model.Item; import org.apollo.game.model.Position; import org.apollo.game.model.def.EquipmentDefinition; import org.apollo.game.model.entity.EquipmentConstants; +import org.apollo.game.model.entity.setting.Gender; import org.apollo.game.model.inv.Inventory; -import org.apollo.game.model.setting.Gender; import org.apollo.game.sync.block.AnimationBlock; import org.apollo.game.sync.block.AppearanceBlock; import org.apollo.game.sync.block.ChatBlock; From 9089b57e62b1255616de397b5768fe989681a3d9 Mon Sep 17 00:00:00 2001 From: Ryley Kimmel Date: Sun, 1 Mar 2015 11:07:12 -0500 Subject: [PATCH 50/59] Fix documentation typo. --- src/org/apollo/update/resource/ResourceProvider.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/org/apollo/update/resource/ResourceProvider.java b/src/org/apollo/update/resource/ResourceProvider.java index 2c6f9960..dcb1e254 100644 --- a/src/org/apollo/update/resource/ResourceProvider.java +++ b/src/org/apollo/update/resource/ResourceProvider.java @@ -21,7 +21,7 @@ public interface ResourceProvider { public boolean accept(String path) throws IOException; /** - * The resource data, as a {@link ByteBuffer}, wrapped in an {@link Optional}. + * Gets the resource data, as a {@link ByteBuffer}, wrapped in an {@link Optional}. * * @param path The path to the resource. * @return A {@code ByteBuffer} representation of a resource if it exists otherwise {@link Optional#empty()} is From 884dd440e93ef6ea90db9989508fcf34519b7745 Mon Sep 17 00:00:00 2001 From: Ryley Kimmel Date: Sun, 1 Mar 2015 13:41:17 -0500 Subject: [PATCH 51/59] Fix events only being sent on re-connect. --- src/org/apollo/net/session/LoginSession.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/org/apollo/net/session/LoginSession.java b/src/org/apollo/net/session/LoginSession.java index 0dfb07db..3fb9c221 100644 --- a/src/org/apollo/net/session/LoginSession.java +++ b/src/org/apollo/net/session/LoginSession.java @@ -131,7 +131,7 @@ public final class LoginSession extends Session { future.addListener(ChannelFutureListener.CLOSE); } - if (optional.isPresent() && request.isReconnecting()) { + if (optional.isPresent() && !request.isReconnecting()) { optional.get().sendInitialMessages(); } } From 25a41d392a72c6a681733c7fa0608afb2cb9669a Mon Sep 17 00:00:00 2001 From: Major- Date: Sun, 1 Mar 2015 18:42:31 +0000 Subject: [PATCH 52/59] Make MembershipStatus an enumeration. --- .../message/impl/IdAssignmentMessage.java | 15 ++--- src/org/apollo/game/model/entity/Player.java | 16 ++++- .../entity/setting/MembershipStatus.java | 58 +++++++++++++++++++ .../io/player/impl/BinaryPlayerLoader.java | 33 ++++++----- .../io/player/impl/BinaryPlayerSaver.java | 32 +++++----- .../io/player/impl/DummyPlayerLoader.java | 3 +- 6 files changed, 114 insertions(+), 43 deletions(-) create mode 100644 src/org/apollo/game/model/entity/setting/MembershipStatus.java diff --git a/src/org/apollo/game/message/impl/IdAssignmentMessage.java b/src/org/apollo/game/message/impl/IdAssignmentMessage.java index aaadda5b..72e50362 100644 --- a/src/org/apollo/game/message/impl/IdAssignmentMessage.java +++ b/src/org/apollo/game/message/impl/IdAssignmentMessage.java @@ -1,6 +1,7 @@ package org.apollo.game.message.impl; import org.apollo.game.message.Message; +import org.apollo.game.model.entity.setting.MembershipStatus; /** * A {@link Message} sent to the client that specifies the local id and membership status of the current player. @@ -15,17 +16,17 @@ public final class IdAssignmentMessage extends Message { private final int id; /** - * The membership flag. + * The MembershipStatus. */ - private final boolean members; + private final MembershipStatus members; /** * Creates the local id message. * * @param id The id. - * @param members The membership flag. + * @param members The MembershipStatus. */ - public IdAssignmentMessage(int id, boolean members) { + public IdAssignmentMessage(int id, MembershipStatus members) { this.id = id; this.members = members; } @@ -40,12 +41,12 @@ public final class IdAssignmentMessage extends Message { } /** - * Gets the membership flag. + * Gets whether or not the Player is a {@link MembershipStatus#PAID paying member}. * - * @return The membership flag. + * @return {@code true} if the Player is a paying member, {@code false} if not. */ public boolean isMembers() { - return members; + return members == MembershipStatus.PAID; } } \ No newline at end of file diff --git a/src/org/apollo/game/model/entity/Player.java b/src/org/apollo/game/model/entity/Player.java index 8b02a12b..50e1aeee 100644 --- a/src/org/apollo/game/model/entity/Player.java +++ b/src/org/apollo/game/model/entity/Player.java @@ -19,6 +19,7 @@ import org.apollo.game.model.Appearance; import org.apollo.game.model.Position; import org.apollo.game.model.World; import org.apollo.game.model.area.Sector; +import org.apollo.game.model.entity.setting.MembershipStatus; import org.apollo.game.model.entity.setting.PrivacyState; import org.apollo.game.model.entity.setting.PrivilegeLevel; import org.apollo.game.model.entity.setting.ScreenBrightness; @@ -131,9 +132,9 @@ public final class Player extends Mob { private transient Position lastKnownSector; /** - * The membership flag. + * The MembershipStatus of this Player. */ - private transient boolean members = false; + private transient MembershipStatus members = MembershipStatus.FREE; /** * A flag indicating if the player is new. @@ -558,6 +559,15 @@ public final class Player extends Mob { * @return {@code true} if so, {@code false} if not. */ public boolean isMembers() { + return members == MembershipStatus.PAID; + } + + /** + * Gets the {@link MembershipStatus} of this Player. + * + * @return The MembershipStatus. + */ + public MembershipStatus getMembershipStatus() { return members; } @@ -830,7 +840,7 @@ public final class Player extends Mob { * * @param members The new membership flag. */ - public void setMembers(boolean members) { + public void setMembers(MembershipStatus members) { this.members = members; } diff --git a/src/org/apollo/game/model/entity/setting/MembershipStatus.java b/src/org/apollo/game/model/entity/setting/MembershipStatus.java new file mode 100644 index 00000000..c02f86f3 --- /dev/null +++ b/src/org/apollo/game/model/entity/setting/MembershipStatus.java @@ -0,0 +1,58 @@ +package org.apollo.game.model.entity.setting; + +import java.util.Arrays; +import java.util.Optional; + +/** + * The membership status of a Player. + * + * @author Major + */ +public enum MembershipStatus { + + /** + * The free membership status. + */ + FREE(0), + + /** + * The paid membership status. + */ + PAID(1); + + /** + * Gets the MembershipStatus with the specified value. + * + * @param value The integer value of the MembershipStatus. + * @return The MembershipStatus. + * @throws IllegalArgumentException If no MembershipStatus with the specified the value exists. + */ + public static MembershipStatus valueOf(int value) { + Optional optional = Arrays.stream(values()).filter(status -> status.value == value).findAny(); + return optional.orElseThrow(() -> new IllegalArgumentException("Illegal membership status value.")); + } + + /** + * The integer value of this MembershipStatus. + */ + private final int value; + + /** + * Creates the MembershipStatus. + * + * @param value The integer value. + */ + private MembershipStatus(int value) { + this.value = value; + } + + /** + * Gets the value of this MembershipStatus. + * + * @return The value. + */ + public int getValue() { + return value; + } + +} \ No newline at end of file diff --git a/src/org/apollo/io/player/impl/BinaryPlayerLoader.java b/src/org/apollo/io/player/impl/BinaryPlayerLoader.java index 00d2fe89..204dbe43 100644 --- a/src/org/apollo/io/player/impl/BinaryPlayerLoader.java +++ b/src/org/apollo/io/player/impl/BinaryPlayerLoader.java @@ -21,6 +21,7 @@ import org.apollo.game.model.entity.attr.BooleanAttribute; import org.apollo.game.model.entity.attr.NumericalAttribute; import org.apollo.game.model.entity.attr.StringAttribute; import org.apollo.game.model.entity.setting.Gender; +import org.apollo.game.model.entity.setting.MembershipStatus; import org.apollo.game.model.entity.setting.PrivacyState; import org.apollo.game.model.entity.setting.PrivilegeLevel; import org.apollo.game.model.entity.setting.ScreenBrightness; @@ -69,7 +70,7 @@ public final class BinaryPlayerLoader implements PlayerLoader { credentials.setPassword(pass); PrivilegeLevel privilegeLevel = PrivilegeLevel.valueOf(in.readByte()); - boolean members = in.readBoolean(); + MembershipStatus members = MembershipStatus.valueOf(in.readByte()); // read settings PrivacyState chatPrivacy = PrivacyState.valueOf(in.readByte(), true); @@ -166,21 +167,21 @@ public final class BinaryPlayerLoader implements PlayerLoader { String name = StreamUtil.readString(in); AttributeType type = AttributeType.valueOf(in.read()); switch (type) { - case BOOLEAN: - attribute = new BooleanAttribute(in.read() == 1); - break; - case DOUBLE: - attribute = new NumericalAttribute(in.readDouble()); - break; - case LONG: - attribute = new NumericalAttribute(in.readLong()); - break; - case STRING: - case SYMBOL: - attribute = new StringAttribute(StreamUtil.readString(in), type == AttributeType.SYMBOL); - break; - default: - throw new IllegalArgumentException("Undefined attribute type: " + type + "."); + case BOOLEAN: + attribute = new BooleanAttribute(in.read() == 1); + break; + case DOUBLE: + attribute = new NumericalAttribute(in.readDouble()); + break; + case LONG: + attribute = new NumericalAttribute(in.readLong()); + break; + case STRING: + case SYMBOL: + attribute = new StringAttribute(StreamUtil.readString(in), type == AttributeType.SYMBOL); + break; + default: + throw new IllegalArgumentException("Undefined attribute type: " + type + "."); } attributes.put(name, attribute); } diff --git a/src/org/apollo/io/player/impl/BinaryPlayerSaver.java b/src/org/apollo/io/player/impl/BinaryPlayerSaver.java index 082731cf..5a0f9e50 100644 --- a/src/org/apollo/io/player/impl/BinaryPlayerSaver.java +++ b/src/org/apollo/io/player/impl/BinaryPlayerSaver.java @@ -39,7 +39,7 @@ public final class BinaryPlayerSaver implements PlayerSaver { StreamUtil.writeString(out, player.getUsername()); StreamUtil.writeString(out, player.getCredentials().getPassword()); out.writeByte(player.getPrivilegeLevel().toInteger()); - out.writeBoolean(player.isMembers()); + out.writeByte(player.getMembershipStatus().getValue()); // write settings out.writeByte(player.getChatPrivacy().toInteger(true)); @@ -118,21 +118,21 @@ public final class BinaryPlayerSaver implements PlayerSaver { out.writeByte(type.getValue()); switch (type) { - case BOOLEAN: - out.writeByte((Boolean) attribute.getValue() ? 1 : 0); - break; - case DOUBLE: - out.writeDouble((Double) attribute.getValue()); - break; - case LONG: - out.writeLong((Long) attribute.getValue()); - break; - case STRING: - case SYMBOL: - StreamUtil.writeString(out, (String) attribute.getValue()); - break; - default: - throw new IllegalArgumentException("Undefined attribute type " + type + "."); + case BOOLEAN: + out.writeByte((Boolean) attribute.getValue() ? 1 : 0); + break; + case DOUBLE: + out.writeDouble((Double) attribute.getValue()); + break; + case LONG: + out.writeLong((Long) attribute.getValue()); + break; + case STRING: + case SYMBOL: + StreamUtil.writeString(out, (String) attribute.getValue()); + break; + default: + throw new IllegalArgumentException("Undefined attribute type " + type + "."); } } diff --git a/src/org/apollo/io/player/impl/DummyPlayerLoader.java b/src/org/apollo/io/player/impl/DummyPlayerLoader.java index 95cd971d..83b0aedf 100644 --- a/src/org/apollo/io/player/impl/DummyPlayerLoader.java +++ b/src/org/apollo/io/player/impl/DummyPlayerLoader.java @@ -2,6 +2,7 @@ package org.apollo.io.player.impl; import org.apollo.game.model.Position; import org.apollo.game.model.entity.Player; +import org.apollo.game.model.entity.setting.MembershipStatus; import org.apollo.game.model.entity.setting.PrivilegeLevel; import org.apollo.io.player.PlayerLoader; import org.apollo.io.player.PlayerLoaderResponse; @@ -26,7 +27,7 @@ public final class DummyPlayerLoader implements PlayerLoader { Player player = new Player(credentials, DEFAULT_POSITION); player.setPrivilegeLevel(PrivilegeLevel.ADMINISTRATOR); - player.setMembers(true); + player.setMembers(MembershipStatus.PAID); return new PlayerLoaderResponse(status, player); } From 794bd49607022ad762e364ab682240a45ac0019b Mon Sep 17 00:00:00 2001 From: Ryley Kimmel Date: Sun, 1 Mar 2015 14:38:00 -0500 Subject: [PATCH 53/59] Basic implementation of player context menu action management. --- data/plugins/player-action/login.rb | 6 +++ data/plugins/player-action/player-action.rb | 59 +++++++++++++++++++++ data/plugins/player-action/plugin.xml | 15 ++++++ 3 files changed, 80 insertions(+) create mode 100644 data/plugins/player-action/login.rb create mode 100644 data/plugins/player-action/player-action.rb create mode 100644 data/plugins/player-action/plugin.xml diff --git a/data/plugins/player-action/login.rb b/data/plugins/player-action/login.rb new file mode 100644 index 00000000..ee2c78d3 --- /dev/null +++ b/data/plugins/player-action/login.rb @@ -0,0 +1,6 @@ +java_import 'org.apollo.game.model.entity.Player' + +on :login do |event, player| + show_action(player, TRADE_ACTION) + show_action(player, FOLLOW_ACTION) +end \ No newline at end of file diff --git a/data/plugins/player-action/player-action.rb b/data/plugins/player-action/player-action.rb new file mode 100644 index 00000000..46144a49 --- /dev/null +++ b/data/plugins/player-action/player-action.rb @@ -0,0 +1,59 @@ +require 'java' + +java_import 'org.apollo.game.message.impl.SetPlayerActionMessage' +java_import 'org.apollo.game.model.entity.Player' + +class PlayerAction + attr_reader :slot, :primary, :name + + def initialize(slot, primary, name) + index = [ :first, :second, :third, :fourth, :fifth ].find_index(slot) + raise "Unsupport action slot #{slot}." if index.nil? + + @slot = index + @primary = primary + @name = name + end + +end + +ATTACK_ACTION = PlayerAction.new(:third, true, 'Attack') +CHALLENGE_ACTION = PlayerAction.new(:third, true, 'Challenge') +TRADE_ACTION = PlayerAction.new(:fourth, true, 'Trade with') +FOLLOW_ACTION = PlayerAction.new(:fifth, true, 'Follow') + +# Shows multiple context menu action for the specified player +def show_actions(player, *actions) + raise 'Must specify at least one action to show' if actions.nil? + + actions.each do |action| + player.add_action(action) + player.send(SetPlayerActionMessage.new(action.name, action.slot, action.primary)) + end +end + +# Shows a single context menu action for the specified player +def show_action(player, action) + show_actions(player, action) +end + +# Hides a context menu action for the specified player +def hide_action(player, action) + show_action(player, PlayerAction.new('null', action.slot, action.primary)) +end + +class Player + + def actions + @actions ||= {} + end + + def add_action(action) + actions[action.slot] = action.name + end + + def has_action(action) + return actions[action.slot] == action.name + end + +end \ No newline at end of file diff --git a/data/plugins/player-action/plugin.xml b/data/plugins/player-action/plugin.xml new file mode 100644 index 00000000..82a7d15f --- /dev/null +++ b/data/plugins/player-action/plugin.xml @@ -0,0 +1,15 @@ + + + player-action + 1 + Player actions + Manages player right click actions + + Ryley + + + + + + + \ No newline at end of file From d74d2fc98759ab1bef63231eef71045ac23105e1 Mon Sep 17 00:00:00 2001 From: Major- Date: Sun, 1 Mar 2015 19:40:00 +0000 Subject: [PATCH 54/59] Make server exit if it could not bind to a port. --- src/org/apollo/Server.java | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/org/apollo/Server.java b/src/org/apollo/Server.java index dc97737c..4812f475 100644 --- a/src/org/apollo/Server.java +++ b/src/org/apollo/Server.java @@ -107,18 +107,19 @@ public final class Server { * @param jagGrabAddress The JAGGRAB address to bind to. */ public void bind(SocketAddress serviceAddress, SocketAddress httpAddress, SocketAddress jagGrabAddress) { - logger.fine("Binding service listener to address: " + serviceAddress + "..."); - serviceBootstrap.bind(serviceAddress); - - logger.fine("Binding HTTP listener to address: " + httpAddress + "..."); try { - httpBootstrap.bind(httpAddress); - } catch (Throwable t) { - logger.log(Level.WARNING, "Binding to HTTP failed: client will use JAGGRAB as a fallback (not recommended)!", t); - } + logger.fine("Binding service listener to address: " + serviceAddress + "..."); + serviceBootstrap.bind(serviceAddress).sync(); - logger.fine("Binding JAGGRAB listener to address: " + jagGrabAddress + "..."); - jagGrabBootstrap.bind(jagGrabAddress); + logger.fine("Binding HTTP listener to address: " + httpAddress + "..."); + httpBootstrap.bind(httpAddress).sync(); + + logger.fine("Binding JAGGRAB listener to address: " + jagGrabAddress + "..."); + jagGrabBootstrap.bind(jagGrabAddress).sync(); + } catch (Exception e) { + logger.log(Level.SEVERE, "Binding to a port failed: ensure apollo isn't already running.", e); + System.exit(1); + } logger.info("Ready for connections."); } From 1899a929153c1c570e692b4286adde253188afaa Mon Sep 17 00:00:00 2001 From: Ryley Kimmel Date: Sun, 1 Mar 2015 15:06:17 -0500 Subject: [PATCH 55/59] Rebase the StatefulFrameDecoder and write response codes for invalid received data. --- .../net/codec/game/GamePacketDecoder.java | 8 +-- .../apollo/net/codec/login/LoginDecoder.java | 59 +++++++++++-------- src/org/apollo/util/StatefulFrameDecoder.java | 37 +----------- 3 files changed, 41 insertions(+), 63 deletions(-) diff --git a/src/org/apollo/net/codec/game/GamePacketDecoder.java b/src/org/apollo/net/codec/game/GamePacketDecoder.java index 5434ce1e..947cd87f 100644 --- a/src/org/apollo/net/codec/game/GamePacketDecoder.java +++ b/src/org/apollo/net/codec/game/GamePacketDecoder.java @@ -4,7 +4,6 @@ import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; -import java.io.IOException; import java.util.List; import net.burtleburtle.bob.rand.IsaacRandom; @@ -61,7 +60,7 @@ public final class GamePacketDecoder extends StatefulFrameDecoder out, GameDecoderState state) throws IOException { + protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out, GameDecoderState state) { switch (state) { case GAME_OPCODE: decodeOpcode(in, out); @@ -96,9 +95,8 @@ public final class GamePacketDecoder extends StatefulFrameDecoder out) throws IOException { + private void decodeOpcode(ByteBuf buffer, List out) { if (buffer.isReadable()) { int encryptedOpcode = buffer.readUnsignedByte(); opcode = encryptedOpcode - random.nextInt() & 0xFF; @@ -121,7 +119,7 @@ public final class GamePacketDecoder extends StatefulFrameDecoder /** * The secure random number generator. */ - private static final SecureRandom random = new SecureRandom(); + private static final SecureRandom RANDOM = new SecureRandom(); /** * The login packet length. @@ -54,11 +54,11 @@ public final class LoginDecoder extends StatefulFrameDecoder * Creates the login decoder with the default initial state. */ public LoginDecoder() { - super(LoginDecoderState.LOGIN_HANDSHAKE, true); + super(LoginDecoderState.LOGIN_HANDSHAKE); } @Override - protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out, LoginDecoderState state) throws Exception { + protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out, LoginDecoderState state) { switch (state) { case LOGIN_HANDSHAKE: decodeHandshake(ctx, in, out); @@ -70,7 +70,7 @@ public final class LoginDecoder extends StatefulFrameDecoder decodePayload(ctx, in, out); break; default: - throw new IllegalStateException("Invalid login decoder state."); + throw new IllegalStateException("Invalid login decoder state: " + state); } } @@ -84,7 +84,7 @@ public final class LoginDecoder extends StatefulFrameDecoder private void decodeHandshake(ChannelHandlerContext ctx, ByteBuf buffer, List out) { if (buffer.isReadable()) { usernameHash = buffer.readUnsignedByte(); - serverSeed = random.nextLong(); + serverSeed = RANDOM.nextLong(); ByteBuf response = ctx.alloc().buffer(17); response.writeByte(LoginConstants.STATUS_EXCHANGE_DATA); @@ -102,14 +102,14 @@ public final class LoginDecoder extends StatefulFrameDecoder * @param ctx The channel handler context. * @param buffer The buffer. * @param out The {@link List} of objects to pass forward through the pipeline. - * @throws IOException If the login type sent by the client is invalid. */ - private void decodeHeader(ChannelHandlerContext ctx, ByteBuf buffer, List out) throws IOException { + private void decodeHeader(ChannelHandlerContext ctx, ByteBuf buffer, List out) { if (buffer.readableBytes() >= 2) { int loginType = buffer.readUnsignedByte(); if (loginType != LoginConstants.TYPE_STANDARD && loginType != LoginConstants.TYPE_RECONNECTION) { - throw new IOException("Invalid login type."); + writeResponseCode(ctx, LoginConstants.STATUS_LOGIN_SERVER_REJECTED_SESSION); + return; } reconnecting = loginType == LoginConstants.TYPE_RECONNECTION; @@ -125,9 +125,8 @@ public final class LoginDecoder extends StatefulFrameDecoder * @param ctx The channel handler context. * @param buffer The buffer. * @param out The {@link List} of objects to pass forward through the pipeline. - * @throws Exception If an error occurs. */ - private void decodePayload(ChannelHandlerContext ctx, ByteBuf buffer, List out) throws Exception { + private void decodePayload(ChannelHandlerContext ctx, ByteBuf buffer, List out) { if (buffer.readableBytes() >= loginLength) { ByteBuf payload = buffer.readBytes(loginLength); int clientVersion = 255 - payload.readUnsignedByte(); @@ -136,7 +135,8 @@ public final class LoginDecoder extends StatefulFrameDecoder int lowMemoryFlag = payload.readUnsignedByte(); if (lowMemoryFlag != 0 && lowMemoryFlag != 1) { - throw new Exception("Invalid value for low memory flag."); + writeResponseCode(ctx, LoginConstants.STATUS_LOGIN_SERVER_REJECTED_SESSION); + return; } boolean lowMemory = lowMemoryFlag == 1; @@ -148,7 +148,8 @@ public final class LoginDecoder extends StatefulFrameDecoder int securePayloadLength = payload.readUnsignedByte(); if (securePayloadLength != loginLength - 41) { - throw new Exception("Secure payload length mismatch."); + writeResponseCode(ctx, LoginConstants.STATUS_LOGIN_SERVER_REJECTED_SESSION); + return; } ByteBuf securePayload = payload.readBytes(securePayloadLength); @@ -160,13 +161,15 @@ public final class LoginDecoder extends StatefulFrameDecoder int secureId = securePayload.readUnsignedByte(); if (secureId != 10) { - throw new Exception("Invalid secure payload id."); + writeResponseCode(ctx, LoginConstants.STATUS_LOGIN_SERVER_REJECTED_SESSION); + return; } long clientSeed = securePayload.readLong(); long reportedServerSeed = securePayload.readLong(); if (reportedServerSeed != serverSeed) { - throw new Exception("Server seed mismatch."); + writeResponseCode(ctx, LoginConstants.STATUS_LOGIN_SERVER_REJECTED_SESSION); + return; } int uid = securePayload.readInt(); @@ -174,10 +177,9 @@ public final class LoginDecoder extends StatefulFrameDecoder String username = BufferUtil.readString(securePayload); String password = BufferUtil.readString(securePayload); - if (password.length() < 6 || password.length() > 20) { - throw new Exception("Invalid password."); - } else if (username.isEmpty() || username.length() > 12) { - throw new Exception("Invalid username."); + if (password.length() < 6 || password.length() > 20 || username.isEmpty() || username.length() > 12) { + writeResponseCode(ctx, LoginConstants.STATUS_INVALID_CREDENTIALS); + return; } int[] seed = new int[4]; @@ -196,14 +198,23 @@ public final class LoginDecoder extends StatefulFrameDecoder PlayerCredentials credentials = new PlayerCredentials(username, password, usernameHash, uid); IsaacRandomPair randomPair = new IsaacRandomPair(encodingRandom, decodingRandom); - LoginRequest request = new LoginRequest(credentials, randomPair, reconnecting, lowMemory, releaseNumber, archiveCrcs, - clientVersion); + LoginRequest request = new LoginRequest(credentials, randomPair, reconnecting, lowMemory, releaseNumber, archiveCrcs, clientVersion); out.add(request); - if (buffer.isReadable()) { - out.add(buffer.readBytes(buffer.readableBytes())); - } } } + /** + * Writes a response code to the client and closes the current channel. + * + * @param ctx The context of the channel handler. + * @param responseCode The response code to write. + */ + private void writeResponseCode(ChannelHandlerContext ctx, int responseCode) { + ByteBuf buffer = ctx.alloc().buffer(1); + buffer.writeByte(responseCode); + + ctx.writeAndFlush(buffer).addListener(ChannelFutureListener.CLOSE); + } + } \ No newline at end of file diff --git a/src/org/apollo/util/StatefulFrameDecoder.java b/src/org/apollo/util/StatefulFrameDecoder.java index c34ee522..18234ec2 100644 --- a/src/org/apollo/util/StatefulFrameDecoder.java +++ b/src/org/apollo/util/StatefulFrameDecoder.java @@ -5,8 +5,7 @@ import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.ByteToMessageDecoder; import java.util.List; - -import com.google.common.base.Preconditions; +import java.util.Objects; /** * A stateful implementation of a {@link ByteToMessageDecoder} which may be extended and used by other classes. The @@ -17,7 +16,7 @@ import com.google.common.base.Preconditions; * The current state is supplied as a parameter in the {@link StatefulFrameDecoder#decode} and * {@link StatefulFrameDecoder#decodeLast} methods. * - * This class is not thread safe: it is recommended that the state is only set in the decode methods overriden. + * This class is not thread safe: it is recommended that the state is only set in the decode methods overridden. * * @author Graham * @param The state enumeration. @@ -36,17 +35,6 @@ public abstract class StatefulFrameDecoder> extends ByteToMess * @throws NullPointerException If the state is {@code null}. */ public StatefulFrameDecoder(T state) { - this(state, false); - } - - /** - * Creates the stateful frame decoder with the specified initial state and unwrap flag. - * - * @param state The initial state. - * @param unwrap The unwrap flag. - * @throws NullPointerException If the state is {@code null}. - */ - public StatefulFrameDecoder(T state, boolean unwrap) { setState(state); } @@ -66,24 +54,6 @@ public abstract class StatefulFrameDecoder> extends ByteToMess */ protected abstract void decode(ChannelHandlerContext ctx, ByteBuf in, List out, T state) throws Exception; - @Override - protected final void decodeLast(ChannelHandlerContext ctx, ByteBuf in, List out) { - decodeLast(ctx, in, out, state); - } - - /** - * Decodes remaining data before the channel is closed into a frame. You may override this method, but it is not - * required. If you do not, remaining data will be discarded! - * - * @param ctx The current context of this handler. - * @param in The cumulative buffer, which may contain zero or more bytes. - * @param out The {@link List} of objects to pass forward through the pipeline. - * @param state The current state. The state may be changed by calling {@link #setState}. - */ - protected void decodeLast(ChannelHandlerContext ctx, ByteBuf in, List out, T state) { - - } - /** * Sets a new state. * @@ -91,8 +61,7 @@ public abstract class StatefulFrameDecoder> extends ByteToMess * @throws NullPointerException If the state is {@code null}. */ public final void setState(T state) { - Preconditions.checkNotNull(state, "State cannot be null."); - this.state = state; + this.state = Objects.requireNonNull(state, "State cannot be null."); } } \ No newline at end of file From 03c1fe16ac1a41a3acaba430d98e43c8bfce8b2d Mon Sep 17 00:00:00 2001 From: Major- Date: Mon, 2 Mar 2015 03:57:15 +0000 Subject: [PATCH 56/59] Improve attributes code. --- data/plugins/entity/attributes/attributes.rb | 32 ++++---- .../impl/PlayerDesignMessageHandler.java | 1 - src/org/apollo/game/model/entity/Mob.java | 4 +- src/org/apollo/game/model/entity/Player.java | 75 +++++++------------ .../game/model/entity/attr/Attribute.java | 18 ++++- .../entity/attr/AttributeDefinition.java | 64 +++++++++++++--- .../game/model/entity/attr/AttributeMap.java | 62 +++++++++++++-- .../entity/attr/AttributePersistence.java | 2 +- .../model/entity/attr/BooleanAttribute.java | 10 +++ .../model/entity/attr/NumericalAttribute.java | 13 ++++ .../model/entity/attr/StringAttribute.java | 12 +++ .../io/player/impl/BinaryPlayerLoader.java | 23 ++---- .../io/player/impl/BinaryPlayerSaver.java | 46 ++---------- .../io/player/impl/BinaryPlayerUtil.java | 4 +- 14 files changed, 217 insertions(+), 149 deletions(-) diff --git a/data/plugins/entity/attributes/attributes.rb b/data/plugins/entity/attributes/attributes.rb index 75183026..370593e2 100644 --- a/data/plugins/entity/attributes/attributes.rb +++ b/data/plugins/entity/attributes/attributes.rb @@ -16,7 +16,7 @@ java_import 'org.apollo.game.model.entity.attr.StringAttribute' # Declares an attribute and adds its definition. def declare_attribute(name, default, persistence=:transient) raise "Attribute #{name} clashes with an existing variable." if (Player.method_defined?(name) || Mob.method_defined?(name) || Npc.method_defined?(name)) - AttributeMap::add_definition(name.to_s, AttributeDefinition.new(default, get_persistence(persistence), get_type(default))) + AttributeMap::define(name.to_s, AttributeDefinition.new(default, get_persistence(persistence), get_type(default))) end @@ -25,35 +25,35 @@ private # The existing Mob class. class Mob - # Overrides method_missing + # Overrides method_missing to implement the functionality. def method_missing(symbol, *args) name = symbol.to_s.strip if name[-1] == "=" raise "Expected argument count of 1, received #{args.length}" unless args.length == 1 - name = name[0...-1].strip # Drop the equals + name = name[0...-1].strip # Drop the equals and trim whitespace. set_attribute(name, to_attribute(args[0])) elsif AttributeMap::get_definition(name).nil? super(symbol, *args) else - attribute = get_attribute(name); definition = AttributeMap::get_definition(name) - value = attribute.nil? ? definition.default : attribute.value - - return (definition.type == AttributeType::SYMBOL) ? value.to_sym : value + attribute = get_attribute(name) + value = attribute.value + return (attribute.type == AttributeType::SYMBOL) ? value.to_sym : value end end +end + + # Gets the appropriate attribute for the specified value. - def to_attribute(value) - case value - when String, Symbol then return StringAttribute.new(value.to_s, value.is_a?(Symbol)) - when Integer, Float then return NumericalAttribute.new(value) - when TrueClass, FalseClass then return BooleanAttribute.new(value) - else raise "Undefined attribute type #{value.class}." - end +def to_attribute(value) + case value + when String, Symbol then return StringAttribute.new(value.to_s, value.is_a?(Symbol)) + when Integer, Float then return NumericalAttribute.new(value) + when TrueClass, FalseClass then return BooleanAttribute.new(value) + else raise "Undefined attribute type #{value.class}." end - end # Gets the attribute type of the specified value. @@ -72,5 +72,5 @@ end def get_persistence(persistence) raise "Undefined persistence type #{persistence}." unless [ :persistent, :transient ].include?(persistence) - return (persistence == :persistent) ? AttributePersistence::SERIALIZED : AttributePersistence::TRANSIENT + return (persistence == :persistent) ? AttributePersistence::PERSISTENT : AttributePersistence::TRANSIENT end \ No newline at end of file diff --git a/src/org/apollo/game/message/handler/impl/PlayerDesignMessageHandler.java b/src/org/apollo/game/message/handler/impl/PlayerDesignMessageHandler.java index 7c4db500..7e7ad3af 100644 --- a/src/org/apollo/game/message/handler/impl/PlayerDesignMessageHandler.java +++ b/src/org/apollo/game/message/handler/impl/PlayerDesignMessageHandler.java @@ -16,7 +16,6 @@ public final class PlayerDesignMessageHandler extends MessageHandler getAttribute(String name) { - return attributes.getAttribute(name); + return attributes.get(name); } /** @@ -369,7 +369,7 @@ public abstract class Mob extends Entity { * @param value The attribute. */ public final void setAttribute(String name, Attribute value) { - attributes.setAttribute(name, value); + attributes.set(name, value); } /** diff --git a/src/org/apollo/game/model/entity/Player.java b/src/org/apollo/game/model/entity/Player.java index 50e1aeee..79f9efc1 100644 --- a/src/org/apollo/game/model/entity/Player.java +++ b/src/org/apollo/game/model/entity/Player.java @@ -19,6 +19,11 @@ import org.apollo.game.model.Appearance; import org.apollo.game.model.Position; import org.apollo.game.model.World; import org.apollo.game.model.area.Sector; +import org.apollo.game.model.entity.attr.Attribute; +import org.apollo.game.model.entity.attr.AttributeDefinition; +import org.apollo.game.model.entity.attr.AttributeMap; +import org.apollo.game.model.entity.attr.AttributePersistence; +import org.apollo.game.model.entity.attr.NumericalAttribute; import org.apollo.game.model.entity.setting.MembershipStatus; import org.apollo.game.model.entity.setting.PrivacyState; import org.apollo.game.model.entity.setting.PrivilegeLevel; @@ -55,6 +60,11 @@ import com.google.common.base.Preconditions; */ public final class Player extends Mob { + static { + AttributeMap.define("run_energy", AttributeDefinition.forInt(100, AttributePersistence.PERSISTENT)); + AttributeMap.define("client_version", AttributeDefinition.forInt(0, AttributePersistence.TRANSIENT)); + } + /** * The player's appearance. */ @@ -75,12 +85,6 @@ public final class Player extends Mob { */ private transient Deque clicks = new ArrayDeque<>(); - /** - * The version of the client this player is using. This is not the same as the release number, instead denoting the - * custom version. - */ - private transient int clientVersion; - /** * This player's credentials. */ @@ -136,11 +140,6 @@ public final class Player extends Mob { */ private transient MembershipStatus members = MembershipStatus.FREE; - /** - * A flag indicating if the player is new. - */ - private boolean newPlayer = false; - /** * This player's prayer icon. */ @@ -156,11 +155,6 @@ public final class Player extends Mob { */ private final transient Deque queuedMessages = new ArrayDeque<>(); - /** - * The player's run energy. - */ - private int runEnergy = 100; - /** * A flag indicating if this player is running. */ @@ -327,7 +321,8 @@ public final class Player extends Mob { * @return The version. */ public int getClientVersion() { - return clientVersion; + Attribute version = attributes.get("client_version"); + return version.getValue(); } /** @@ -436,7 +431,8 @@ public final class Player extends Mob { * @return The run energy. */ public int getRunEnergy() { - return runEnergy; + Attribute energy = attributes.get("run_energy"); + return energy.getValue(); } /** @@ -571,15 +567,6 @@ public final class Player extends Mob { return members; } - /** - * Checks if this player has logged in before. - * - * @return A flag indicating if the player is new. - */ - public boolean isNew() { - return newPlayer; - } - /** * Checks if this player is running. * @@ -701,9 +688,6 @@ public final class Player extends Mob { blockSet.add(SynchronizationBlock.createAppearanceBlock(this)); send(new IdAssignmentMessage(index, members)); // TODO should this be sent when we reconnect? sendMessage("Welcome to RuneScape."); - if (newPlayer) { - interfaceSet.openWindow(InterfaceConstants.AVATAR_DESIGN); - } int[] tabs = InterfaceConstants.DEFAULT_INVENTORY_TABS; for (int tab = 0; tab < tabs.length; tab++) { @@ -734,7 +718,7 @@ public final class Player extends Mob { * @param filterable Whether or not the message can be filtered. */ public void sendMessage(String message, boolean filterable) { - if (clientVersion > 0) { + if (getClientVersion() > 0) { send(new ServerChatMessage(message, filterable)); } else if (!filterable || !filteringMessages) { send(new ServerChatMessage(message)); @@ -791,12 +775,12 @@ public final class Player extends Mob { } /** - * Sets the value denoting the client's modified version. TODO make this an attribute? + * Sets the value denoting the client's modified version. * - * @param clientVersion The client version. + * @param version The client version. */ - public void setClientVersion(int clientVersion) { - this.clientVersion = clientVersion; + public void setClientVersion(int version) { + attributes.set("client_version", new NumericalAttribute(version)); } /** @@ -844,15 +828,6 @@ public final class Player extends Mob { this.members = members; } - /** - * Sets the new player flag. TODO make this an attribute? - * - * @param newPlayer A flag indicating if the player has played before. - */ - public void setNew(boolean newPlayer) { - this.newPlayer = newPlayer; - } - /** * Sets the player's prayer icon. TODO make this an attribute? * @@ -872,13 +847,13 @@ public final class Player extends Mob { } /** - * Sets the player's run energy. TODO make this an attribute? + * Sets the player's run energy. * - * @param runEnergy The energy. + * @param energy The energy. */ - public void setRunEnergy(int runEnergy) { - this.runEnergy = runEnergy; - send(new UpdateRunEnergyMessage(runEnergy)); + public void setRunEnergy(int energy) { + attributes.set("run_energy", new NumericalAttribute(energy)); + send(new UpdateRunEnergyMessage(energy)); } /** @@ -969,7 +944,7 @@ public final class Player extends Mob { @Override public String toString() { return MoreObjects.toStringHelper(this).add("username", getUsername()).add("privilege", privilegeLevel) - .add("client version", clientVersion).toString(); + .add("client version", getClientVersion()).toString(); } /** diff --git a/src/org/apollo/game/model/entity/attr/Attribute.java b/src/org/apollo/game/model/entity/attr/Attribute.java index 9fff080f..6627b8a0 100644 --- a/src/org/apollo/game/model/entity/attr/Attribute.java +++ b/src/org/apollo/game/model/entity/attr/Attribute.java @@ -13,12 +13,12 @@ public abstract class Attribute { /** * The type of this attribute. */ - private final AttributeType type; + protected final AttributeType type; /** * The value of this attribute. */ - protected T value; + protected final T value; /** * Creates the attribute with the specified {@link AttributeType} and value. @@ -31,6 +31,13 @@ public abstract class Attribute { this.value = value; } + /** + * Encodes this Attribute into a byte array. + * + * @return The byte array. + */ + public abstract byte[] encode(); + /** * Gets the type of this attribute. * @@ -49,4 +56,11 @@ public abstract class Attribute { return value; } + /** + * Returns the Sting representation of this Attribute. Will be used to write this Attribute as a String, if + * required. + */ + @Override + public abstract String toString(); + } \ No newline at end of file diff --git a/src/org/apollo/game/model/entity/attr/AttributeDefinition.java b/src/org/apollo/game/model/entity/attr/AttributeDefinition.java index 9a48b15d..0f4092b1 100644 --- a/src/org/apollo/game/model/entity/attr/AttributeDefinition.java +++ b/src/org/apollo/game/model/entity/attr/AttributeDefinition.java @@ -10,25 +10,69 @@ package org.apollo.game.model.entity.attr; public final class AttributeDefinition { /** - * The default value of this definition. + * Creates an AttributeDefinition for a {@code boolean}. + * + * @param defaultValue The default value of the definition. + * @param persistence The {@link AttributePersistence} of the definition. + * @return The AttributeDefinition. + */ + public static AttributeDefinition forBoolean(boolean defaultValue, AttributePersistence persistence) { + return new AttributeDefinition<>(defaultValue, persistence, AttributeType.BOOLEAN); + } + + /** + * Creates an AttributeDefinition for a {@code double}. + * + * @param defaultValue The default value of the definition. + * @param persistence The {@link AttributePersistence} of the definition. + * @return The AttributeDefinition. + */ + public static AttributeDefinition forDouble(double defaultValue, AttributePersistence persistence) { + return new AttributeDefinition<>(defaultValue, persistence, AttributeType.DOUBLE); + } + + /** + * Creates an AttributeDefinition for an {@code int}. + * + * @param defaultValue The default value of the definition. + * @param persistence The {@link AttributePersistence} of the definition. + * @return The AttributeDefinition. + */ + public static AttributeDefinition forInt(int defaultValue, AttributePersistence persistence) { + return new AttributeDefinition<>(defaultValue, persistence, AttributeType.LONG); + } + + /** + * Creates an AttributeDefinition for a String. + * + * @param defaultValue The default value of the definition. + * @param persistence The {@link AttributePersistence} of the definition. + * @return The AttributeDefinition. + */ + public static AttributeDefinition forString(String defaultValue, AttributePersistence persistence) { + return new AttributeDefinition<>(defaultValue, persistence, AttributeType.STRING); + } + + /** + * The default value of the Attribute. */ private final T defaultValue; /** - * The persistence state of this definition. + * The persistence state of the Attribute. */ private final AttributePersistence persistence; /** - * The type of this definition. + * The type of the Attribute. */ private final AttributeType type; /** - * Creates the attribute definition. + * Creates the AttributeDefinition. * * @param defaultValue The default value. - * @param persistence The {@link AttributePersistence} state. + * @param persistence The {@link AttributePersistence}. * @param type The {@link AttributeType}. */ public AttributeDefinition(T defaultValue, AttributePersistence persistence, AttributeType type) { @@ -38,7 +82,7 @@ public final class AttributeDefinition { } /** - * Gets the default value of this attribute definition. + * Gets the default value of this AttributeDefinition. * * @return The default value. */ @@ -47,18 +91,18 @@ public final class AttributeDefinition { } /** - * Gets the persistence state of this attribute definition. + * Gets the {@link AttributePersistence} of this AttributeDefinition. * - * @return The persistence. + * @return The AttributePersistence. */ public AttributePersistence getPersistence() { return persistence; } /** - * Gets the {@link AttributeType} of this definition. + * Gets the {@link AttributeType} of this AttributeDefinition * - * @return The attribute type. + * @return The AttributeType. */ public AttributeType getType() { return type; diff --git a/src/org/apollo/game/model/entity/attr/AttributeMap.java b/src/org/apollo/game/model/entity/attr/AttributeMap.java index 0d79d68e..e1f0ce9b 100644 --- a/src/org/apollo/game/model/entity/attr/AttributeMap.java +++ b/src/org/apollo/game/model/entity/attr/AttributeMap.java @@ -3,6 +3,8 @@ package org.apollo.game.model.entity.attr; import java.util.HashMap; import java.util.Map; +import org.jruby.RubySymbol; + import com.google.common.base.Preconditions; /** @@ -12,10 +14,15 @@ import com.google.common.base.Preconditions; */ public final class AttributeMap { + /** + * The default size of the map. + */ + private static final int DEFAULT_MAP_SIZE = 2; + /** * The map of attribute names to definitions. */ - private static Map> definitions = new HashMap<>(1); + private static Map> definitions = new HashMap<>(); /** * Registers an {@link AttributeDefinition}. @@ -23,7 +30,7 @@ public final class AttributeMap { * @param name The name of the attribute. * @param definition The definition. */ - public static void addDefinition(String name, AttributeDefinition definition) { + public static void define(String name, AttributeDefinition definition) { definitions.put(name, definition); } @@ -33,8 +40,9 @@ public final class AttributeMap { * @param name The name of the attribute. * @return The attribute definition. */ - public static AttributeDefinition getDefinition(String name) { - return definitions.get(name); + @SuppressWarnings("unchecked") + public static AttributeDefinition getDefinition(String name) { + return (AttributeDefinition) definitions.get(name); } /** @@ -46,10 +54,20 @@ public final class AttributeMap { return new HashMap<>(definitions); } + /** + * Returns whether or not an {@link AttributeDefinition} with the specified name exists. + * + * @param name The name of the AttributeDefinition. + * @return {@code true} if the AttributeDefinition exists, {@code false} if not. + */ + public static boolean hasDefinition(String name) { + return definitions.containsKey(name); + } + /** * The map of attribute names to attributes. */ - private Map> attributes = new HashMap<>(); + private Map> attributes = new HashMap<>(DEFAULT_MAP_SIZE); /** * Gets the {@link Attribute} with the specified name. @@ -57,8 +75,13 @@ public final class AttributeMap { * @param name The name of the attribute. * @return The attribute. */ - public Attribute getAttribute(String name) { - return attributes.get(name); + @SuppressWarnings("unchecked") + public Attribute get(String name) { + AttributeDefinition definition = getDefinition(name); + Preconditions.checkNotNull(definition, "Attributes must be defined before their value can be retreived."); + + return (Attribute) attributes.computeIfAbsent(name, + key -> createAttribute(definition.getDefault(), definition.getType())); } /** @@ -76,9 +99,32 @@ public final class AttributeMap { * @param name The name of the attribute. * @param attribute The attribute. */ - public void setAttribute(String name, Attribute attribute) { + public void set(String name, Attribute attribute) { Preconditions.checkNotNull(getDefinition(name), "Attributes must be defined before their value can be set."); attributes.put(name, attribute); } + /** + * Creates an {@link Attribute} with the specified value and {@link AttributeType}. + * + * @param value The value of the Attribute. + * @param type The AttributeType. + * @return The Attribute. + */ + private Attribute createAttribute(T value, AttributeType type) { + switch (type) { + case LONG: + case DOUBLE: + return new NumericalAttribute((Integer) value); + case STRING: + return new StringAttribute((String) value); + case SYMBOL: + return new StringAttribute(((RubySymbol) value).asJavaString(), true); + case BOOLEAN: + return new BooleanAttribute((Boolean) value); + } + + throw new IllegalArgumentException("Unrecognised type " + type + "."); + } + } \ No newline at end of file diff --git a/src/org/apollo/game/model/entity/attr/AttributePersistence.java b/src/org/apollo/game/model/entity/attr/AttributePersistence.java index 29cb365f..5c86de00 100644 --- a/src/org/apollo/game/model/entity/attr/AttributePersistence.java +++ b/src/org/apollo/game/model/entity/attr/AttributePersistence.java @@ -8,7 +8,7 @@ public enum AttributePersistence { /** * The serialized persistence type, indicating that the attribute will be saved. */ - SERIALIZED, + PERSISTENT, /** * The transient persistence type, indicating that the attribute will not be saved. diff --git a/src/org/apollo/game/model/entity/attr/BooleanAttribute.java b/src/org/apollo/game/model/entity/attr/BooleanAttribute.java index e5409c66..e9df53d1 100644 --- a/src/org/apollo/game/model/entity/attr/BooleanAttribute.java +++ b/src/org/apollo/game/model/entity/attr/BooleanAttribute.java @@ -16,4 +16,14 @@ public final class BooleanAttribute extends Attribute { super(AttributeType.BOOLEAN, value); } + @Override + public byte[] encode() { + return new byte[] { (byte) (value ? 1 : 0) }; + } + + @Override + public String toString() { + return Boolean.toString(value); + } + } \ No newline at end of file diff --git a/src/org/apollo/game/model/entity/attr/NumericalAttribute.java b/src/org/apollo/game/model/entity/attr/NumericalAttribute.java index a7f21982..ffc3915b 100644 --- a/src/org/apollo/game/model/entity/attr/NumericalAttribute.java +++ b/src/org/apollo/game/model/entity/attr/NumericalAttribute.java @@ -1,5 +1,7 @@ package org.apollo.game.model.entity.attr; +import com.google.common.primitives.Longs; + /** * An {@link Attribute} with a numerical value. * @@ -26,4 +28,15 @@ public final class NumericalAttribute extends Attribute { super(typeOf(value), value); } + @Override + public byte[] encode() { + long encoded = (type == AttributeType.DOUBLE) ? Double.doubleToLongBits((double) value) : (long) value; + return Longs.toByteArray(encoded); + } + + @Override + public String toString() { + return (type == AttributeType.DOUBLE) ? Double.toString((double) value) : Long.toString((long) value); + } + } \ No newline at end of file diff --git a/src/org/apollo/game/model/entity/attr/StringAttribute.java b/src/org/apollo/game/model/entity/attr/StringAttribute.java index be7c763c..6468ee11 100644 --- a/src/org/apollo/game/model/entity/attr/StringAttribute.java +++ b/src/org/apollo/game/model/entity/attr/StringAttribute.java @@ -1,5 +1,7 @@ package org.apollo.game.model.entity.attr; +import java.nio.charset.Charset; + /** * An {@link Attribute} with a string value. * @@ -26,4 +28,14 @@ public final class StringAttribute extends Attribute { super(symbol ? AttributeType.SYMBOL : AttributeType.STRING, value); } + @Override + public byte[] encode() { + return value.getBytes(Charset.forName("UTF-8")); + } + + @Override + public String toString() { + return value; + } + } \ No newline at end of file diff --git a/src/org/apollo/io/player/impl/BinaryPlayerLoader.java b/src/org/apollo/io/player/impl/BinaryPlayerLoader.java index 204dbe43..19d77500 100644 --- a/src/org/apollo/io/player/impl/BinaryPlayerLoader.java +++ b/src/org/apollo/io/player/impl/BinaryPlayerLoader.java @@ -58,35 +58,28 @@ public final class BinaryPlayerLoader implements PlayerLoader { } try (DataInputStream in = new DataInputStream(new FileInputStream(file))) { - // read credentials and privileges String name = StreamUtil.readString(in); - String pass = StreamUtil.readString(in); + String password = StreamUtil.readString(in); - if (!name.equalsIgnoreCase(credentials.getUsername()) || !SCryptUtil.check(credentials.getPassword(), pass)) { + if (!name.equalsIgnoreCase(credentials.getUsername()) || !SCryptUtil.check(credentials.getPassword(), password)) { return new PlayerLoaderResponse(LoginConstants.STATUS_INVALID_CREDENTIALS); } - // set the credentials password to the scrypted one - credentials.setPassword(pass); + credentials.setPassword(password); // Update password to the hashed one. PrivilegeLevel privilegeLevel = PrivilegeLevel.valueOf(in.readByte()); MembershipStatus members = MembershipStatus.valueOf(in.readByte()); - // read settings PrivacyState chatPrivacy = PrivacyState.valueOf(in.readByte(), true); PrivacyState friendPrivacy = PrivacyState.valueOf(in.readByte(), false); PrivacyState tradePrivacy = PrivacyState.valueOf(in.readByte(), false); int runEnergy = in.readByte(); ScreenBrightness brightness = ScreenBrightness.valueOf(in.readByte()); - // read position int x = in.readUnsignedShort(); int y = in.readUnsignedShort(); int height = in.readUnsignedByte(); - // read appearance - boolean designed = in.readBoolean(); - int genderIntValue = in.readUnsignedByte(); Gender gender = genderIntValue == Gender.MALE.toInteger() ? Gender.MALE : Gender.FEMALE; int[] style = new int[7]; @@ -107,15 +100,12 @@ public final class BinaryPlayerLoader implements PlayerLoader { player.setRunEnergy(runEnergy); player.setScreenBrightness(brightness); - player.setNew(designed); player.setAppearance(new Appearance(gender, style, colors)); - // read inventories readInventory(in, player.getInventory()); readInventory(in, player.getEquipment()); readInventory(in, player.getBank()); - // read skills int size = in.readUnsignedByte(); SkillSet skills = player.getSkillSet(); skills.stopFiringEvents(); @@ -139,7 +129,7 @@ public final class BinaryPlayerLoader implements PlayerLoader { int ignoreCount = in.readByte(); List ignores = new ArrayList<>(ignoreCount); - for (int i = 0; i < ignoreCount; i++) { + for (int times = 0; times < ignoreCount; times++) { ignores.add(NameUtil.decodeBase37(in.readLong())); } player.setIgnoredUsernames(ignores); @@ -161,11 +151,12 @@ public final class BinaryPlayerLoader implements PlayerLoader { private static Map> readAttributes(DataInputStream in) throws IOException { int count = in.readInt(); Map> attributes = new HashMap<>(count); - Attribute attribute; - for (int i = 0; i < count; i++) { + for (int times = 0; times < count; times++) { String name = StreamUtil.readString(in); AttributeType type = AttributeType.valueOf(in.read()); + Attribute attribute; + switch (type) { case BOOLEAN: attribute = new BooleanAttribute(in.read() == 1); diff --git a/src/org/apollo/io/player/impl/BinaryPlayerSaver.java b/src/org/apollo/io/player/impl/BinaryPlayerSaver.java index 5a0f9e50..5fca15a2 100644 --- a/src/org/apollo/io/player/impl/BinaryPlayerSaver.java +++ b/src/org/apollo/io/player/impl/BinaryPlayerSaver.java @@ -17,7 +17,6 @@ import org.apollo.game.model.entity.SkillSet; import org.apollo.game.model.entity.attr.Attribute; import org.apollo.game.model.entity.attr.AttributeMap; import org.apollo.game.model.entity.attr.AttributePersistence; -import org.apollo.game.model.entity.attr.AttributeType; import org.apollo.game.model.inv.Inventory; import org.apollo.io.player.PlayerSaver; import org.apollo.util.NameUtil; @@ -35,27 +34,22 @@ public final class BinaryPlayerSaver implements PlayerSaver { File file = BinaryPlayerUtil.getFile(player.getUsername()); try (DataOutputStream out = new DataOutputStream(new FileOutputStream(file))) { - // write credentials and privileges StreamUtil.writeString(out, player.getUsername()); StreamUtil.writeString(out, player.getCredentials().getPassword()); out.writeByte(player.getPrivilegeLevel().toInteger()); out.writeByte(player.getMembershipStatus().getValue()); - // write settings out.writeByte(player.getChatPrivacy().toInteger(true)); out.writeByte(player.getFriendPrivacy().toInteger(false)); out.writeByte(player.getTradePrivacy().toInteger(false)); out.writeByte(player.getRunEnergy()); out.writeByte(player.getScreenBrightness().toInteger()); - // write position Position position = player.getPosition(); out.writeShort(position.getX()); out.writeShort(position.getY()); out.writeByte(position.getHeight()); - // write appearance - out.writeBoolean(player.isNew()); Appearance appearance = player.getAppearance(); out.writeByte(appearance.getGender().toInteger()); int[] style = appearance.getStyle(); @@ -66,14 +60,11 @@ public final class BinaryPlayerSaver implements PlayerSaver { for (int color : colors) { out.writeByte(color); } - out.flush(); - // write inventories writeInventory(out, player.getInventory()); writeInventory(out, player.getEquipment()); writeInventory(out, player.getBank()); - // write skills SkillSet skills = player.getSkillSet(); out.writeByte(skills.size()); for (int id = 0; id < skills.size(); id++) { @@ -95,47 +86,20 @@ public final class BinaryPlayerSaver implements PlayerSaver { } Set>> attributes = player.getAttributes().entrySet(); - attributes.removeIf(e -> AttributeMap.getDefinition(e.getKey()).getPersistence() != AttributePersistence.SERIALIZED); + attributes.removeIf(e -> AttributeMap.getDefinition(e.getKey()).getPersistence() != AttributePersistence.PERSISTENT); out.writeInt(attributes.size()); for (Entry> entry : attributes) { String name = entry.getKey(); StreamUtil.writeString(out, name); - saveAttribute(out, entry.getValue()); + + Attribute attribute = entry.getValue(); + out.writeByte(attribute.getType().getValue()); + out.write(attribute.encode()); } } } - /** - * Writes an {@link Attribute} to the specified output stream. - * - * @param out The output stream. - * @param attribute The attribute. - * @throws IOException If an I/O error occurs. - */ - private static void saveAttribute(DataOutputStream out, Attribute attribute) throws IOException { - AttributeType type = attribute.getType(); - - out.writeByte(type.getValue()); - switch (type) { - case BOOLEAN: - out.writeByte((Boolean) attribute.getValue() ? 1 : 0); - break; - case DOUBLE: - out.writeDouble((Double) attribute.getValue()); - break; - case LONG: - out.writeLong((Long) attribute.getValue()); - break; - case STRING: - case SYMBOL: - StreamUtil.writeString(out, (String) attribute.getValue()); - break; - default: - throw new IllegalArgumentException("Undefined attribute type " + type + "."); - } - } - /** * Writes an inventory to the specified output stream. * diff --git a/src/org/apollo/io/player/impl/BinaryPlayerUtil.java b/src/org/apollo/io/player/impl/BinaryPlayerUtil.java index 85ce31b5..9c4ca633 100644 --- a/src/org/apollo/io/player/impl/BinaryPlayerUtil.java +++ b/src/org/apollo/io/player/impl/BinaryPlayerUtil.java @@ -32,8 +32,8 @@ public final class BinaryPlayerUtil { * @return The file. */ public static File getFile(String username) { - username = NameUtil.decodeBase37(NameUtil.encodeBase37(username)); - return new File(SAVED_GAMES_DIRECTORY, username + ".dat"); + String filtered = NameUtil.decodeBase37(NameUtil.encodeBase37(username)); + return new File(SAVED_GAMES_DIRECTORY, filtered + ".dat"); } /** From 01f227f0710b386c98b23ee30d4eed8e5de5e301 Mon Sep 17 00:00:00 2001 From: Major- Date: Mon, 2 Mar 2015 03:57:32 +0000 Subject: [PATCH 57/59] Remove AVATAR_DESIGN constant from InterfaceConstants. --- src/org/apollo/game/model/inter/InterfaceConstants.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/org/apollo/game/model/inter/InterfaceConstants.java b/src/org/apollo/game/model/inter/InterfaceConstants.java index d16e6cbb..d0e44330 100644 --- a/src/org/apollo/game/model/inter/InterfaceConstants.java +++ b/src/org/apollo/game/model/inter/InterfaceConstants.java @@ -7,11 +7,6 @@ package org.apollo.game.model.inter; */ public class InterfaceConstants { - /** - * The avatar design interface id. - */ - public static final int AVATAR_DESIGN = 3559; - /** * The default inventory tab ids. */ From 0591256fbfb6e9422e0c9df1014617629a51f0e2 Mon Sep 17 00:00:00 2001 From: Major- Date: Mon, 2 Mar 2015 06:25:38 +0000 Subject: [PATCH 58/59] Add height level support to matrices in Sector. --- src/org/apollo/game/model/area/Sector.java | 10 ++++++---- .../model/area/collision/CollisionMatrix.java | 16 +++++++++++++++- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/org/apollo/game/model/area/Sector.java b/src/org/apollo/game/model/area/Sector.java index 3f582fe1..642ef928 100644 --- a/src/org/apollo/game/model/area/Sector.java +++ b/src/org/apollo/game/model/area/Sector.java @@ -52,7 +52,7 @@ public final class Sector { /** * The CollisionMatrix. */ - private final CollisionMatrix matrix = new CollisionMatrix(SECTOR_SIZE, SECTOR_SIZE); + private final CollisionMatrix[] matrices = CollisionMatrix.createMatrices(Position.HEIGHT_LEVELS, SECTOR_SIZE, SECTOR_SIZE); /** * Creates a new sector. @@ -207,13 +207,15 @@ public final class Sector { * Returns whether or not an Entity of the specified {@link EntityType type} can traverse the tile at the specified * coordinate pair. * - * @param x The x coordinate. - * @param y The y coordinate. + * @param position The {@link Position} of the tile. * @param entity The {@link EntityType}. * @param direction The {@link Direction} the Entity is approaching from. * @return {@code true} if the tile at the specified coordinate pair is traversable, {@code false} if not. */ - public boolean traversable(int x, int y, EntityType entity, Direction direction) { + public boolean traversable(Position position, EntityType entity, Direction direction) { + CollisionMatrix matrix = matrices[position.getHeight()]; + int x = position.getLocalX(), y = position.getLocalY(); + return matrix.traversable(x, y, entity, direction); } diff --git a/src/org/apollo/game/model/area/collision/CollisionMatrix.java b/src/org/apollo/game/model/area/collision/CollisionMatrix.java index 6c370591..075c49a8 100644 --- a/src/org/apollo/game/model/area/collision/CollisionMatrix.java +++ b/src/org/apollo/game/model/area/collision/CollisionMatrix.java @@ -15,6 +15,20 @@ import com.google.common.base.Preconditions; */ public final class CollisionMatrix { + /** + * Creates an array of CollisionMatrix objects, all of the specified width and length. + * + * @param count The length of the array to create. + * @param width The width of each CollisionMatrix. + * @param length The length of each CollisionMatrix. + * @return The array of CollisionMatrix objects. + */ + public static CollisionMatrix[] createMatrices(int count, int width, int length) { + CollisionMatrix[] matrices = new CollisionMatrix[count]; + Arrays.setAll(matrices, index -> new CollisionMatrix(width, length)); + return matrices; + } + /** * Indicates that all types of traversal are allowed. */ @@ -174,7 +188,7 @@ public final class CollisionMatrix { * @return {@code true} if the tile at the specified coordinate pair is traversable, {@code false} if not. */ public boolean traversable(int x, int y, EntityType entity, Direction direction) { - CollisionFlag[] flags = (entity == EntityType.PROJECTILE) ? CollisionFlag.projectiles() : CollisionFlag.mobs(); + CollisionFlag[] flags = CollisionFlag.forType(entity); int north = 0, east = 1, south = 2, west = 3; switch (direction) { From 4ae78658dfa46ea65b250ccbfa31e30b7a7cfca4 Mon Sep 17 00:00:00 2001 From: Major- Date: Mon, 2 Mar 2015 06:27:38 +0000 Subject: [PATCH 59/59] Add Sector#getMatrix method. --- src/org/apollo/game/model/area/Sector.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/org/apollo/game/model/area/Sector.java b/src/org/apollo/game/model/area/Sector.java index 642ef928..3c0b3e89 100644 --- a/src/org/apollo/game/model/area/Sector.java +++ b/src/org/apollo/game/model/area/Sector.java @@ -146,6 +146,17 @@ public final class Sector { return ImmutableSet.copyOf(filtered); } + /** + * Gets the {@link CollisionMatrix} at the specified height level. + * + * @param height The height level. + * @return The CollisionMatrix. + */ + public CollisionMatrix getMatrix(int height) { + Preconditions.checkElementIndex(height, matrices.length, "Matrix height level must be [0, " + matrices.length + ")."); + return matrices[height]; + } + /** * Moves the {@link Entity} that was in the specified {@code old} {@link Position}, to the current position of the * Entity.