From 9a32b3afdda54e513cd370a0edfa87febc5cd1f0 Mon Sep 17 00:00:00 2001 From: Zoryn Aaron Date: Tue, 1 Mar 2016 01:35:52 -0500 Subject: [PATCH] trying to get custom content working - do NOT try to implement cc yet --- Release/StardewModdingAPI.exe | Bin 55296 -> 73216 bytes StardewModdingAPI/Events.cs | 25 + StardewModdingAPI/Extensions.cs | 11 + .../Inheritance/Menus/SGameMenu.cs | 60 ++ .../Inheritance/Menus/SInventoryPage.cs | 26 + StardewModdingAPI/Inheritance/SGame.cs | 99 +++- .../Inheritance/SGameLocation.cs | 90 +++ StardewModdingAPI/Inheritance/SObject.cs | 188 ++++++ StardewModdingAPI/Program.cs | 120 +++- StardewModdingAPI/StardewModdingAPI.csproj | 9 + ...rdewModdingAPI.csproj.FileListAbsolute.txt | 1 + Vanilla Items List.txt | 538 ++++++++++++++++++ 12 files changed, 1153 insertions(+), 14 deletions(-) create mode 100644 StardewModdingAPI/Inheritance/Menus/SGameMenu.cs create mode 100644 StardewModdingAPI/Inheritance/Menus/SInventoryPage.cs create mode 100644 StardewModdingAPI/Inheritance/SGameLocation.cs create mode 100644 StardewModdingAPI/Inheritance/SObject.cs create mode 100644 Vanilla Items List.txt diff --git a/Release/StardewModdingAPI.exe b/Release/StardewModdingAPI.exe index ad8ffbd1dc9d1409a79b707146e58d435a225cc0..620cc96de1e0ae4dda89c99a415860e96bd60217 100644 GIT binary patch literal 73216 zcmdSC34D~*)jxioXO>JR0WuJhuqFWlla;Uwq7VW|WR;+zC@@JTVazh&nF$b)7%Ecx ziVM}^)+#QvTG85;x?Ayed9`Y*t^2DM)Gl_hwY9#rD*nFb-22QtGYQN4zQ51!^Z!S4 z=APxAd+xdC?svk{bFU^B5xMdE)mKCh;*)>o3OqLG1$$uO!vpC+=8MG-8cSX*UbP_- zE9$hOEmo+#s4>*h5seo$go~`Mj-p6M(fsB0MeWh1aMgeT{&8CMiUmYV3>Qs3>D9CB z(hiYnWEok652E3U+EI*j5z=$<$<}e&RCXgpUIzTr3qI)l;+His_nMLKwe*E z#jHjU#5UMS1wh>Rbo|VP^;K55Eeb)lm0+{@U}PV;d5&z7T)}?D58Gyvhu+=@9rv>D zh=v$Rx3bKM{0ymfQ8fgiHDGQ)j+S@m3FURuJt!A043L?B#i=kM+m}~Z^c`Om&FasgyesB_<~J>r+ZoLVO_h5Z zi!*D8JK)X}?ri~gL4FjT_WQkgHwHZjuPkr=jmHq9@=P+7AZ6rAeFjs8cN?<0Gol$1 zpXEcy0^XT-1uQUvwc_2f(PnTM3Mzx`L#j;}FTM}B%&q4kZxrG0_m`7b@!fPM_~@&F zTz_mM6l76`>2k;5QSUaE?}2J}hRQl3QN;yhm7w5!DOjqhM7F|PZd6v;B6+=)gEEeI z;RSCD;Vwl-MI=ps#Y~zE2TZVoP3GuaoxCkAp`<0Dc9V3 zK1z=k=~7TZZvRrqz)68v42t|-a~lhhGVO>rZrdd`WtCHg?YGHVxAG?9z_pDlXS%nc zM7IY`g4XtXD}5>qa$Kfo8~o@dDc2;#i`YggXcO{ zDpri@^l~HU`cy$LS|`wh7?7@Ds;+=Kn%NgK5j_ExI(x#KN6#x=;lGs^gHYdcnRo)_ zCi6PVJ;A)0{guna6DT*C*HP{X=0!vFtuGT#pxk6$N4Y1M7t>YWa+!Dnpl3j8xzLAlnTT@Hv5r=5T3#vlMDrp7 z0zCs$%Y{Ca%S4omj&Zbd)ACBWCz=-#5a=0{S}ydVTqdGiIPPfWrsb7#Pc$zgAkc&5 zi?e;959Klu<-&1CD>p5#lzZ&F(@Dmt=nNUjMqs?2g0Tycgej>9u5v35y<6OEO*7wW*uD)3$ zJ=2VyEbau#eZ!1mp@DeWg=-Ybkz__svr%qfGrCw%Kb0Nhe|Xu2wu)fR;h!F~ zmb-FD?h$VVGRLL^^fIYjae5Il?w-N6Ol3lbNs!@>UT*9jEZCGD%wSp%lOV$%z1)C3 zxwg#2gbb4)!ymoeC_RWgrKdU}!z9S?M=v|N2MYrwGl^wp0rWBnGW^lYqgf9YY)S?* zy*GyG+S|({$nZxmd$$KGHYJ0|^~UD043i+kAHD4I9xS$$%v6?H$TCcV41e@;JM>`D zrDUeD%;_w{B*^ebFE>sZsr4EvN+>%(LF{P!S%VETSb~Hs*@jem2+dC@H$XjDj=A%S zz5*T{4~gU9u?e;sSr@`C!f$|FW)SUzZm(89ysmMH~8g{aE?t zyCXBZ5Us`#PkSvy^c!PsC51Dc)HRAj-@N$I!;Wa2^>q;$;Z=`CU7iWryWmMn!vGiZ9JZ?G=XF3 z+IKu%X#&U6^&iL6l_qd3U4K5Ft~7yT=^E-jPE4c;^sfucXN)pT_;|X~1dgR^>+y7@2^>q;H;$+4hE#!L>3TXOWzYsT?(r3oBMSKaY+ zr3oBMSLk@U(gcpBtNVDm(gcpBYxnVVr3oBM*W<_2l_t=?E-bJye!bqGE=wLdm+ z*gt(A3wl}NqV8_OnKNH?1SoF|Qk0h$yNmf=GkO+2aq!JsoKtc3?HT9}PUH1G@lme$ z4f;rQzJyuV2u=sLa2)UE^+`IPGeb9F!xx~Wj0vHWY$1DJf(;+`C9o#BFJUCHFTo}T z?feV&!%twC8Qc#j^Az89jF1YUozn#Rwlg+6(DP=0dT^SS(32*Rst19^ehX0Se(kG! zlD-n(xTzMOvKBFe_p!ZOXQIZ@SpZ!gI4k#vOP!MsCF?gZMxW}><5PVq$2m27Jcv!L zy`M_@8fG5X*9n;vU*ig7HZ&&og1B6O&jFJ@X9RpVw;AEO0daw!*u%P>4<_qr$HXaY zBVr=uenrJwk?4n(q<%&c<>L$=`gbxsr@bOE!?B}FxK9TT8pO>_`bq)ngP;_In4m+C7fn}^iobUKzbRc86dr! z(+rSa!D$9apTTJcNU!8H1ElLY%>e0DoMwRZnVe>TG`h5Z8v~@z<}?GOS96*H(&uoR z0n+DkngP;lIL!d*^Ek}_>GL_w0O_@yX5egs0U2pcun*obwyjfH)^ipH$R6S}1Ed=` z%>d~}PBTEdiPH=c=Q1uC!^U!~m^hAm0ih8KLm-%mo)koEmdoIPjx?g$OBWE)IF`jh z&Cehj-2l<7^4WupU<4^Y4r_vt@w@QZiqEZW01+E$XJpJ@$Ht!6E8>7rV+crYe1!8ksGZwWmw__qFhSAFIc&Mll9>w?6# zO)Sl4XX-4G+YE*N3UU&@L#lmL13TDO&|d`|$AP$Los5G@#@wx**4Sn!L1C(4&+CL9H)TCiKq98|aR1 z<>FjD7vaOY1^!7GDQjOj?&Mr-E|FLt+y>cb59ibCj7;hM+o&&7E~Ob6I4LXY~+| zxph1E>eTmZNChupz_H@)*#X$vb17iDRCFhZQh|Wy+;fgA$W?0_%jFXJ=ANrlIdj*v za(3l!w6|2B0_?`#Ir+iMKoRG2jKE5ME8vI`K8ddEq{6xXJ70RWFTGM}hwD7iZ@_?p z)vaS_?#P8}v>(yo6McinD>U_+$-ZF{1|*IbroRq)@ZX>Vp3lmt^jY^H^8DqQiX*)# zsY~~#|4iyq{ZG^1NvHEzg)-hx(oK2GRnGL-ADN7`^W`XAjS*O>vOQ557=Unxj>?Du zg!^suH2_}FvI$WcAAoSVQ5hsK=k0>FZ48jUg3}C;zLL`nkmioDjRDeEahicQe;Y>` z^!=Lk9nvKoX5>9VWO;9oIT#eVZl8i9Ub2^Td^a!x{$-!IWI-WQy<3vOt5Je->X7OT z3K>L|kju@Ebzw0(Ak)PQ0ykyy;y~wUlP4!~a}hiPX-T0|Bd})Of^ul2dO(9doM%0a z#=9-x%~w*=VSpA`A1eB=o-?2~34E14Q@(QAN3uVqjLVCxxf z>lu->#O4LR1wrQ{qTn77#^VYnp~3nXR>&|Gybe4Wlcj&m!=gZS8ER2gFHH; zwm*Y^Gosf65z$`HZCTtDSsC()g2{d`9@T)D98pn;B?26+?DBIPJq-RMI|1()3Sp@)=3+ z15&@KPCg?EKKefDKh4Q!q^!)IwDr8|hkfjep3`j6(Pl5FF>r7nNbnaq_?&j|;n+Y= zorBNmviqrL7C!T$H*yO~I(ie5)}?5|o^K;1*Z0xyFdKHe>F4N7Xawv&{eCa>I999z?0O)uYmnUcU{333yum=I=#qQx^2Q$GM3l+{iu_&<42UQ#? zl}5#C$hwqitX^^Ng$`$*wZ50sB%Mfg;=(V2KY%2r>txnKF8)4%-r1;W4+HDh$ekbk zArntwA_FVSj}_pLn06|oBY-+>mG-vI1XXP9<>p7@<-*3;kCBcY;H+~wYa~4@Q=>lt zpMqyWemoxq^qdT$YT>_G-$>>V*FkZ9s^S_}{6JDn&J==pe(EI%4`X4N?d8{yLK)7K z=}Z}-DFq1%dY;JOfvdX150285QA|0VbHQzBFgznpbpm+mZvS+ayq~MgB;4)uM{qQ# zWSyLrD_G3RdbkS83wZiipOleDkL7p}*%W+$eWYB2IQX+-nTUagFtP8X?bL*pyZDdvwt3@-Y~ySNk(man`78wCTgF#p^rbhGMhaL-_;B z-^x?bRE8xo&b-hq^n0FIJF3~sLxWX}yeU!g2=wGfA7yR9JoZL%*oZy`YVfB3(Z>OL z=RiRZ12o`JcIQE6Jpn*H9D)*-Dmw;7Od-7-GK%o;OrUp1qUMb-!7HA^N5kdc=e{R}@9wmpxUglzd$?VreG+!@<^VK>SBS9C0y}=7mSG8}# z{F&0Kg#)a85OFrNn3k1cy$`xFEyH12hGh)0P0L6(?P{=O0Pka3hBghK@3N`dw2Whz z#%m>s`-^n{pdR!x9@Vjh&!e7Su}2teg`fP}UIn0@`3Z@9hXlLF-@5H}5m}HBK?`#J zqB-*h(Ka|9`4=Xb+0-)+Nbj3W$NIx0=vHS5)&bPhjJ^eqb7+vE(d=?#C`g=D!_NPN zm=J@Q|Gd47QrSZ4d7HB%oV~qgpq%8gQ0hEFmu2rA)Nep+`N>8YmtZe?I`NifwHVE0J;1o7$-yCG3=g9q@(D#m}x&@35X^o#->Tk z2Gd&Tlo*#LaS==GbV`(@Nj%CD&p0KSAj4Sz$qdf` zOL}QWT88Xl$WQ^0%;;qOqY`3F>tMSQZg(qbY_^DmSGLJRumv< z(gP_OW~F6#h%>x+j0`8IWhf~+PKG&Y8K!ZDGXRn%Jr68d>B(ssDvOa}IY2VQ4}m2! zOiIfzcMLL|3y{q460l^3DQOvok41)A0LcuG0ZV3>nwFt*95S25@!jgq-IE*CzN1JRbNE1&oMmY!Z3=pHO|MjV${V_O05X9GG^V5*+o@qrhmS+778L1RZkNZ%i&tJw6_vBBhaffV3Y5WLrt_-ri}~`sTd@pt-{vb&Ijq+q z6mASvj+#@6Vd++9{RM*Z{jQ#+P%7))rR;$BFtzkD2}@M|2o8jJ zvM5;s=?X}hJkPla)4ZNjJ>%__D~8!3kbCuXnP2qPS6^MMk%D4y_@`H$6L^OegUde` zYl1Sh3}27n8C-2G%5J8fWwy1;*jm|0G6~l5huTOca=kAzF>)=pb1hHgViI!kht4&I zf*&Bm__E0q`whE+*E40OQt-E|Cb6mG`eJQEI8;iuf4=MpvVF7ewQ9qDZg7ehU)EoUH8*QzEnnc8k zwb4I;ahoq+A%6y>CxHsy;Ghzsy=PJ^+G z_og$yk5s^8EezV7VG*zuDcIT+tStq*C0p(g@vZ`*KZ)63ok(*ezN z+NIi_+jmxRYU`hll6C8&`FNbecT&;@I?0F4mK`q%neL2+B=HXOJ3%SR|A`Y+a1K0vcRXO?Qxe?!i+hK3jIffa53qjUkg&BvNVI7sWK zU%A0aG`rt2%MzYNoyAZ6^{Xe7?V)|9`qbVOI(sHt^{^da92wHH9z$JaXjJSARH{V0 zlo!OY64Fb!V4Yr#bb(H9x3S~LwdOgT~fd^*c&_o^)vBB zMhbZGUP8WhE?-eci*YxgI{coC-|sMveY*;GAD?mg>7*Bu1mY{2lO9PDaO?#Fj~&uf zzNjgL8eeRBQ(i;>ezr`FsW|5&hO9WxeV5&ccatGG3Cy#4N6LB95d_R18fS zGgL*(jXc~4SFTPK1+SNni{#9x(v?^4>3Ngg-#ZUP>s`1)aWbrbB373BJT>uB|>>`vO0s9fbaNg~&*aAb9A8>*Q?*D5bn zxHm(h5u?!GPtZWv#%queK2LUzO{x?uR2L*l@LSU=?1Aa%3tNo9y*{x5&Fl#B#1aGL zxn#|QjZJbaOw51HiSkkwn`l8^Y}O(cseBF=Y@A9ochY+!`kN_VFZbQQEvsOPgSrz-9-6% z$$n)-P4*zp){@D21;oKgA_pewnoCv$A>r)l<@5V#0B_#VyqF)R=SH)*0@8)9O3SIn z2t5FDOkN9vXZKf^$}Rm>WNDJf=Ebs6k~&cL>SC=QqsYXz!yCOE4VKt)sQrh%MnVrd zrhOxD&buD=ox=9z`OC2n_2%2P#HA9ewq8YXe7Vdwk?2Vy)t!a)N05~SU$Fbt0WrOc zO*G%bLC=o5#D5S}SRX@W6zyK_x3Vfx z=))X}IQR{KnO$CqB{#0b@J(YpQ^j8zQVT+P_5uPfrRApIHUz@BVB|Lg&*CYoc_eRe z>Qh$zmUSG>Ua#J=VhfGSOFsQped!#0_TRTpNj6ck$Bv@>L_g++v-n6Sh#PH=6O18! zBOOJpR8f|fA8f@u8pU|BIQcBQIAVw)#*@aX%P$g{xGBF;Wp2HM7cXpi?p`%OQz z0aa=G)SU4I{LFU`iNmn)r;uCkT$_wyM^oJ}hJnNB_<2|i{<o7XZDgxw$ogWS4hUnA?uw2Z;AN&uHaGLW$^crT12Ew1Z0j0(ZkqSg$a zjZggbi6HKS{K4~>2#Iz0%+4E7KFF7OExJE8HeSliUp*kxCs*#gcm0jZY6j1NY!GKD zJTJ(ub_5i#)*z+;n5mI-MYY_wRt%C4GuQ;0V>>)dUB?E4l22rUVUzHo%mvj#CLN9<9E#c+@2 z?`0B>pZOz*o>m^jkWfCvJs4lB13Q0p5Z6L}r57)VapeQ=UQsR(>zFeDxUgy_(iqRd9sR!er?V;|)L|K|Yk=Cwr|fb)-u zq3!I#`!h5BK>k%Sg&oDE{~LZs;1>=cREE%Zg$^STOhgCp3tw@5`CBlUi3pPmVZq3A zmdG-V`w+Z^AHUEz1os>J3@`l{&`-ZNUIF}@z|RF1o0+DcW}4-I`wfN*k@ixHxdd>e zi}RKO4y0E+_j?A?KLPzT(EAGLjb5h5y*GQj^mQ-GKk2>CJCN$LZidY0?60!C^j7w> z*?xL(&@0AZdLZX!Pad5fC=K}O-axsTM^_Byba^h9dnKTkKFa?f-%BM0&t`k+)PjA+ zaN1hXT;Qee6znP(O~Zz{hI#4DVQke$fTO8=_%3kUM>6Fnqu7Rb#&Ei5taq%JW{zb& zD+IO++$C_Iz@G|yQ{X28E5;2N=cTy24Vy-x~KYWd0?vpoG)q zC0yd{61HTWq?-g@B=Bj01IDxDr19*rWx@O5u?vEn>(bzTUhMxQ{f@vt3;c(`VWsT7 z_EPrGMWtWi`RWyt-U~R8?k#0M9}voQW!+_C=(DoF3hoAtAi@` z8RMy{Vob&DbXo;R#mb5$&~Rl1x7{7!=Fx){rGY$p2GCCnDmm9rE7`(l00&b^)yP(0rHSmZ-vbV& zoNA7ZiPfcn;k3588Et)GHMjLW)z4<<(Z)%o0WV!Mi8bFW@OyxMdTuh?`OC>m;Gf@2 z=Ggw#)K`qpjYCtp2aK6EaN0mRZ`$l>UV3EO2l_>4G(D zY?fd=bTIE!!7kC*Ji)Hl*h0bX(b(xy!qZa12wEn#yo8g+0r+!KXA1TeumHYKxnHnM z<3F)(9Ze5VFRU&w#v2}dC-@QJEi=wDMgen}N~QgE6q%7(yLrQ7>)B-|O%KwqOb1Sp{bR_7xjo#TTHbt8dH<(B}ddjj#6y=)UnxFPQKb-&wt#qgZF}sCyv4 ztI%)<=$=9kj`aVda1h{o0>3I8f^468N6bm+-A@U&v%v3~K|XS0#{r#`cU5zxDuGd%#up#t{#&!V9r5wyau*`Q2 zu%Wa>V?P9zN0({r31Ip3l*WDy3@ZZkNY3{Wuwj^~6qf03#4F-08p{JVf(~eGy1N}? z%U?BiI)JJ*s?)mTY(kQ9U8mAy`75akjCx;R!k%Lz6kkVbYG60=xU9< z2W%`|tFeIRTljYOOB$;HR)UqE=}qefwC1lypoHo+d$SdU;nY?DwPT_xCR zjlJi&6Ixm{_NC`ue1mqA#zuJ$U~IiqV-vj(IvMR= zPT$p7RIs}=cDrEvHTJq-KhRj#1kQ&mNBr!jITP*#_7ja=IN@G=7wbWd{b0fYd@Jt} zjeRiTVT{f{)!4A$Q~XUN{Mb=ftucb54mUkwwgBsiGtu@xr+ZwymyT~|?KGE1Oyi1MqDULN4 zT3W`5wbU!vPT%X^dSfkJC)jr1hu+n|_G;ee-nGU$dO>3YGa7*XNn^zsYmN0(P{}%X z`euQ*o=(zOJ$NB%(pUp{A=;s_jTtRQ1Kp>w-i%gYFKO&5@EYk0jeQ5aMjBbAO1K+3 zn`n{79)Zp#+Mu!L!3)#18ha1CFdfj?XW%u{A&m|8H2_lqyVF{0<0vJ)&CCO1yrrE*THM0^ECDm zc&&7i#ypv8jW)VdW1}(~fIX|RY2dZfCmK5qymrc+q)Ip^v(xCHxf+XP#(}NZST}f4 z+NH6}!Hd#AE|8&w#g)=4efYPCl%)I9~GnabQ7>m4eqrt28zZye^7stOmSIv{z%xz}rLz zHMYjzVr-^AX)Nk*1(q#?%1+-U;BBFkGEy-SM?4YMKc7ApPun#oW z0p6vQgR=>4+wI_8O4S;>7QCHwp2qG4Zzo+O*dE^p*;g4~r)w2PpJsmx*kei(>z8jE zm(fd_H( z3IX;2+sz-)cEO%8{uQ{|ypMJ$jM&Z}QnpO-%GW=l zT*034tr>j4{1KIFtZDFrz@{omUpsg|ro|fD2HuZpmBy|c{Fr%wS~Yh2;C}}e*Vqq` z?BD5!eBZ{ny}5;{keJW8NWgV6SLw=#Wn1LHeV{ zO2B)NKGE1T@E)QpS+wl*Ee7u)%GFqCNQ?0>KVQJlPM{=Cv{+-;g7*lm z(%3%ee3V)>_7muQl;RqDdPukN7+tQh*M{@}yH;brL%yHV-5UD>`F=_V6ejKdI0fgj zEzjWa^nm#|&DGdhfnNc;I)S}yK1nClD9NJS-#QmbH3Wpcc{N^#A5KJS3}8eOh=ujf4o>{`uxAH3J;Zq54(c(2m| z&Eq(GgPzwsj2 zg6)(@ev8UA#wEN(Q#H0MzXc~Qi#2v;ek-t58sjK`n_4x-QT{f?6(+6u4)I?yK>zby zm_N<+4($={1L*!EfW$;H5Y#uAO411!^M5^N7eM*f@2Z}=}@$vt%8 z$lchV1vRz+_dnN1qK*#+3)z@SWF|sA*chjGMst_2KJQZ{rjkcu6*My!FKz8G3t3>A86j& zqpmUvj4u>Me-^B$P3qwLa@6at0%L|?+kIK1e~DAvxtcd@^y{u+#@U)z3f?edz2?mv z{Wf;En>BCc==Xs2YF;aNBaG`b?^5ta7zZ`)7Vt(If7RH5(JjVEBcq*d+3x%K=vH7k zg6;JEe)L*%lrcf`jKbl@D5F~Qh8KS58f~1Wd6NqNMx%`tf<1+E+BsBcd_!aV1lzB% zMTJ+Jg@!N6G%#PD>Xinkx%i;jDISON+)0LD>GaUJIjr1h0*CVF87ri z)f#I8rf&aYum|U!0=orX3~18Vi*s^ZbcIm9De$^J^zR7e4&mONfF}I_X%{iqpa%sy zOZk79eq2g_R^ST)UlDj%Ail2z3y%h!wc{F@DK&C(RVfVntGiQDS;FvmlFC|!$CFew zVt71BRcnU*Nh;g^jCMEapO7)=hy(sv(*G~p?*BVw@xvyA_6%UZJvxwM`w~F6{9QZ) zcLU7rYpu!^KwguEjN#riRP;FIQ)O6lA!OWCB9avX`)aT$T&|r?>bEIQE~h7nHU+0h zdYV9|<;tE}LSG_KNjhcz_vtgC8UMl}pi4Z17v@ryqPGaW6VOfF@Eh*x9NZnky+XLx z0eT?AH_dkd8l*HFK-xu53WeoU%X(Vq|NB~~v627Kt4a7OGfF?&IP**4IwhUy2fN|qiN#7;#hXNl0T!zrl3ngh{E6W?xWE5t$vy6Dij_R( z&IP3wZ*N{Mc^;J4N?wQLTP5!R{uH^gMLuAvT*2`N%wqHG;2KW^Hw^1N+i88U&GQY& zSf0;}aInWyYIX*%0qn*T>d%ae@jmkg+8w;zGs(Oqc$X)W?hdwq{#MC7pga)lG-jGF z1n1CpDdmUsO7LmV59x#8&ppFH`LV0PXMb+zw{K-%+e9AaWublhPPPG z*NP=?Dd5Rwg`{WF($WU+Oxjr547j6oGvGC)y@1~r<;F?L}1fC>tfxtBa8w9osyu0i{$R8{lOf%`FveC%(`?4oM`LgUeK)&0Z zNk;hy&_|X39F&rBE@fIdm(pDR2B1}b81S3re*nC#oaKL1{tu)dEN2^@l)SGC{9}18 zD4z=5U2()a8#S$^C(M}@1sPA6b1P2Dm=8a%&sajY1UF@@qEN*yz}AZ08MjibVh>;! zU=2>f-ZqzzcwT%}Bk)7w(}Eh>T+wQLgLYI*HQq#vpA5?N6%Qh>-}P7qxAK!2&tZN0 zJSab?cvsTzXVlTl6<>n;E^<9bzpXHRHS}>sfr}-FBmJ+65iV}=slIREPjpT->d0R? z!c|8@D!BK$>P zz*SZiHv+CjRiB{T`l`V+3^EUz#V*!X>bj)rU%pb;y;Vl$OxG`~e3>;upXqW<9GF?> zDx6qr)Van_97|_N`V7~Ci9<6#qcbOt1iWD40W;*fXku|@#I5ZrIY~r@>!Vy{_3%~T^wH>&D`ypQytG7=BlsWnt7|Mx%y(jjnz9d?-Fg9#ue4OG6Sv~kZYLn zoocT2!_XXXalgCObth{x#!T7=8}6vQJM#?J#7RGaRVPh)G&8P!TQ}(?P?k^nFw=0Y zo%9jlhDp<0yIsALy#6OpO1A$^x_45pzm6W7ROmlU2Pcid$;{6LzC5YLI828o?a4Sy zzXzp`J_5`{t@mZt;ohjgT}RoI$NFz|4RuxfS^ronHI`1k%TwnHO`hSOWOPiP=f6lS zxz+X5WQ=vLLzCnF4^i$MwA8~BZz3Mqw)vkhV5fe+%i1Nq{#xnv-2GB{VUC*qx2*l3%t0xxU3^oQv!ICoZkJafjTZ0_mb&OXDPH{-|I`^D!^n8Rm0mwiBL{e)SG^nU5-`!No@ z2Kk;Df6Q*v7P6h_>onUvm`VYC_-EnobPdG6u36*8+k0~%V7I_40JAC6wFqz&;9&Ii z+3qTe(F6Eq%2s*`@Dh3vu#v6+yqsPGyoQ!SW(`G=9xHIMz#%jclo7NVuv{op1fDFE zTIw3mXmH+QbBM9jT_Z3gaJ#@;1wJA0Nr8t2zAw;laW0p@Vu51?)(ET>*eGzjz*_}A zA@Hz3!_69s1=a`*3EVF5R)J3lJS@=gh`hiWfgypt0=Em?EAUo<2L(PM@Q}d60`bLp zlxqkq5?Cy7uD}|B>jj1c_6poCaIe5y1s?W^9-NJ#76NMoh6HXGc&osJne68$Bz;&Q z`I%BAaIU}_KkHd9>5!zi3*0O4R)GfvJ|Xb1KqE^^7g!@OB(QfV)AtHIl*eiOsbz-4 z7#0bfD{#G{3}^aWf$IhK3fwF3puj@{X@qDHI9K3$fxQCv3Op$AkU$zK@&e}yTraR! z;9h|T1s)PeqeNcdT$L^q+XSu`*eh_az=Hx038W&H>=n3I;6Z_h1X8hR7C2YndVx*F zS!j#Bl0GQ#DWM#aG>ze0?lCM=B=n3I;6Z_h1QwOC%v^!%1@;O& zBoJSV0JlisT!HHa_6po9@Ss4d5J`b^1+Ev^D{!yCgOx0ENZ@Aob?zUz-*DOi#0?+jFJoM$avtAA1gZe&%__^QPxr&j%i_Hw%Axe1f;ydy03Sx6ZrF zn~||Ja(uOx;yK>tS7Rb$@(g5X!b+d?_?jzHp##)*u)v(eP%Y`Qdcfux4?Y@ zUlEAE{0jPbcL89?JreK=cM;&D?s0(satE<*Fz`OG9Ipba@XB@~-UCj;2zx5t{>{US zztix}?{r8m8*r~dbl!j;1GWn66?pl82SC{)aIaAI3w&JQD+1pV_!ohh16jjxft3Pl z1TG)=2ehW4Pu$>L5~9t6<8>6 zqQFxIu|1~`dJ6C?NjD0#1YS1iInax92E)-+Ir)H7a*6;i%Q+2j&fq%$R}98K_e!OC zV_c9CI4f^F((@#}Jg*$-wRv2-h`=s^U(aK!t`&HzQ0~cN3m=xW(l#ZZb)GCxY3|Ig z2E|#{=6u$pN?bbX7I4=HY#wzx(vKC5bQ8T;R1El95!dDYq6(z{Eby};{KJ?uu$bXE zfzygv+u~xb*ZSfa_`{Ya{_`P1INr{}KHj7=0do*7ZqNq+8nhZ`EhfGT?*TmrCoVpG z!Pg7=xp=*5(m8-Rh$tWa3*gtlJMB!+*8t`q!u+5Ok?)JF#j915&IioFd(v#she~v= zM>!^~1H@Z$l1R4r@3n0I+&jY;>5dUH~$}#Zo{xEEVZj)L84eG!;z@&D8QRu+GJPv5m zM&vWd5*VjqP+|hRu#zxn6QD_(@vhXMEdnpZ3s9_91a8G@#-NJ;P1=UuXi$&9UcA0E z>0*J~(K`+L8lZ`l%Os?C2;7P9)0%Xtz^~(PjTv+qph@4rOG*RZ?P0hJJ5v*D9EMlm z6{SH}0-AIczKd?q)dIhXH54|1@6W75=^=U(4gD!{XLUz6?i+H0m>Z$zf1L??-Tev#Ft6?5lsf& zBk%`^Ad~JDcpsw1z+diK1Ih!46x<>J;x#p*!=UE?P5K!k!l35`{t{7O;=2V5e}$Ge z@K-~^NWY5KHt02hZ=jt`dR^d~Xkmli0_4A=(vI}o0^g-5DDMdTHQL#rLx3jM`Z1*6 z6Zipjf%3k<-=Lih+%<0o<#%XdgMJTa(uY`g8uSN&|3W*P^ckQ*U!a9e`dr|bv>lWq z0tv6MO!^9~ZQ@%Hmjb%+PRbyUzzpp4P4Wu#8JB~e322fZub}YnCjgrGw!~FP4+O-& z?``ZxItLKvo>;9K_+mf9mBzO~IRnt3RmOEl*9$z;xB=<2jhjGUE%039JD{8ch+b^m zg7g}J=Nq?zvKA2i)VLjRy|E9J5Fq{~bK`qRHv*c}WZZ>x81R1glkOaEk@p;L)H^Wa ztck~ULBtAf6ae#R&Cbete3Og*=w^~vfaIWI_LZe0>QwQ_(AlE0E0pK z|G8Z;o)(%@?iRY)!@N}5jX8a3rGa!B#t@!JQ}P7f6;tgl>N1=C#cf(Mdb z{AS=6Z~8G3;?4lSJnH1*w*X_;FpNzjFea6fmpEjC}sT8iI|=GECT^UmyU{BFbV zCFY_GwuxphjW%_)g-@mWc*trBZwA_gFB#UXsH+NZ2~%yfy*<>?)R${>7DlY_B1p7_ zEn2WC+!2q_ytYtBtE6oPbjQQB8$ul|;U-!f?oPpL+aisvp@z2b(r`zYEp%F_J-j5^ z7>Y-t9Wk3&+htiOp$~n*mUy@$#*$P&FWS%$w&sPbz9v`Ib!-S*k$9-1FMeVW1sMQu}p!)6@bL|XWZShEBC>Ea|ZVR`-v35a4XNB6@!reBiFkR84 zTM{)+tFWq~ohebJI@=McYKhe(YRbqYZDv(%6jn4!!&RLY?tsS|X-Om&#{=b+;T9yq zR=7#WRm={fWzb-!=Z9mBcDlxDfehEHNhMW0a?~|ZsHth4R-_14xIMZloJ!-&b`;y? z+xWsrhiwT}HKOr}^${ zRV~EO5Z)ZMTIncs3~-%YaUNi$wPcjl!EDp)Y66cXS#|@|rHsXz?{v9cg|vZLk&oh- zm6#o(?Nk>-ne(HYJJ7Y;(9;x|(_I$TE$HZK4_iD7V3=4Ht;ZD9)rLX5E>_nOpE4QU zPkpMP&^g99^U`VI_@Yp31GR+X>v-f&4tuda6qad_*L8A=0>EVFa~cbCMYI zlyUW)VRWaYu?kP}YZ@CdHCQrvI>b`QN$FJ~3rIgcNMmr0SYxP78Ld)G3vUWr-EsCw z{f1C0#vL@Il-e(Yb2PU_F+f>pYlx5A-VmlaO2w-3=NDJ`}H#z6@Q5v`C@iB|tFD7rBgxiMxbVB;@o0zL`9vax!ZOWm zk-O6tyOcUmHS} zbP5qlAc=Chza*1aB80|vadFxIo3A*;0wJ$qGniwdEbP{M+9TRCwqF44H?pQ_UKdYlO<66vEDA|ibt z1F6sOkSHOAqvwT{;by(|#7ZvQhJ{&kR7zc8MK)o~5h5=-J7RGQ?ad=P&l9z6p;(M( zk5oAjn445JJ7rQiwRIh4nZ{N)NJJ=wOUly3K-KSL(G*F{4323aIp`}L$}cLNQf);_ z8>rRLoE9)DtdBmn+L4nm*Csf|Nt@&x3vHSj^^`qoglk9{%Nzrj9;x_)MV}i5)w>$c}Eu7YwogFvPKSfr0W115aCaNBn(v_S&Az>*8 zeFAZ|VtQn!#vS()jwN1A^72c1QVJolP{UTHGupvB1I`o=HK=YU38r*nH>*f0WrZ8V zkxk*1JRFM>l9;wj>NliqCW%(1$2Jj5KgYJ2hXl4Wl`18qkoqkqMdGMyTsB5_pB&MI zop3Au1v9DBl5n%GQk$JxgfRf@Hmn)KNwy|9e4sU8g(|bLtr7T2mHFuASfNfV*m$hO z(E^SOusozD?5e0y&O7QG5hWcmJ#}?p-NWXHwF}s9D|nx2yOL{WZ&OlQJVC6-W}5em zyiT4Uk?AUAb+1=*4Gt0134v;E2a4eiYqYpie~h|hmzZpQyO2Ij!zV;qaUY%?lXhl4 z$*_&!YRR^qgF+Ha;my4j=}b&VPMl{IEbS)G7nf*EJYlC<0|umU3(jd0x>E>F3B9@C z@@*MSVyU{=3Jm(}N-4sDYHnMoG3;a~aOPv1F%J!EpD5_{cwZ{ZCWY$MvOR^s5=%o{ zFcmkpCYCWN1eQ1(M-NM*T{r|#Dx5g;dC!;_ySc_G1eRFX7HYxy+rp@|0-dI-Q)=CZ z2uWv?a3t4t$QZORWbw+LDQ9m8cSzTQw9~T|H=Iq7_K75&jAX)t7?~sOUG2#_*S290 zBRK?viseXmvT!^4NR7lf&1QXl0&up&*uG31HhmdR8;{Oa!P1wX43&O)b}jod`-Ded z5oc)hINkkM4DNWGX@7I zk8U-|USwb(*A&MApr$y_+!C4^Q*T2wJ<-sLZ6EOIQB#|Zr4_F<&g{UN1Xndp3$`?d zWeyf4>SSGAuFQ|N!#V5vO6u0=CnvT8xWWuHhHzVF>H&Qm=U}l^ z(uPP=+9`f)Lv(YhOe~as($A}_RGILW2s(!I$^f%Uci38o9x4M`5>+vh#O?4&Qq-^{ zF_k2$bEPD%*7zD%D?mLKrqJr+-B@K|J=U@q$&y9t zkWUg|XdhZ#dwUmd9J=j%I4YMBOXmW*6bs!jMZ4nbFgl=na;jZu$`170j-`l*cip*@c+3vZT!Ft*6H8{LE*VxjZ2XwM)eqXa$|Se9bpM4~IaEER{XT zFuNqWIUI{)&|s%v7C_2gJFDZ7L@w2#WL!?C^|$nAeTjv?LU>j{7-Ng1k3CL9^f+-A zSj-f7db5<2#F9L0P0=Pirzx(&nXm0?vu}7XvMCe#WpEDct~N!YU9rAd`sZ*Sx%SY9 zq*8)Y5s%QvkJi7(!XNz?Y_BpU8$ENQjA%>G)cuasTklx91+Sc>aUOzh}V zN#FO8N$(f7dw5lmjQWIY$Qi%=RUG&4{e@?r0JOzY>Y2#wq$Y^TS`fylt}vD*d{t+U zmW@q(=Z%Y)7X-@-)YKeNkG*CSZH_cyHMKz<-pBdCr4^6waJ?Lo zoX)CZ_~LaM%fuWc};aiW%ut;@RF@wS7MTN0byX45=H@%yrB5kWX^Niyt1 zbnOOAm0>H|i9@GNkwzRMVj*=_Bo@JeNixf6U6H0FW*e#<*q5;oG0=ypi=7_{wRA*d z=(sVOA8zPsY2m|{qz*+xqoAAf-GtgL*lh;mI-%ThS_^`#N^yo4+9Ih~Qk~Ao`M_$3 z@C{Rvn|M-`Bqg5PAWH)lLbx7>e-ON_Se=L(D~yG&ocdu7;Fl+II_G4XZLgY7Hg9nW4^&s4m9k;gAw3HG79+JQPp%i>C2)grmH zpRIB!OKR)K%|3PJI-IjLZa}_{Xh(ND=J};EblIK@kt5F}I-xub&ODP(EKj2|&y*9( z)8x!E^~Caooq47a#;Z_!^@(L|c4nP^VtFQ2J2TBV!Az5!nNB*vObEDS>&`sEOj8ms zPk4Ew=A~tPad>(Z+ikV*Ud8Y0EIg@Ga6x+~_9XV}4}O4!ocb*YW4vtBGc|K?aI~Qo zy&ucwO<_@8$K52VPH|NdmjmIrtoDgtkzmfLxAA#V>^?%W^XGA%k17_)ewec`#!E3x znTLLa?0m{37lX+qw7TkRRNLiMp$2v8!^b}%IjK~;6dV+s(S@Zx4tFrHwMAPn=Pz4P z%eMj+$No<44!bf3An$n6nvoU;DB)l2A<11u(UWk`` z*ce1GEL&k^$=P9?RKaFNTf%crOe46<<5Gpj<6R`iC&u{D49LYWh+qQ4q+=iaprP<& zv1(NqvovnnC}#^ylqRne}-4ZPrrcG&A6YGX@JLv3QT zMHV7UL!H!)Uo45RrdZxw-x=E65w0b+nLwdKGX4IyA9 zj8hAmR2nbJEG4J*-oj=#EX3;)#b69)a$OybxK7e@Yb`2jrOg8?*K#xos6?bunB)#V|_9Dp2U^OjorbhD;0> zoAgf1I@!lVdi(60V=*xt$*DcW z5_zP5&xaP-K(Q7+xCc2(=)<@hDwga@%Z-ZO!Z- zj<9qZtJjk#FLkYG8#(4xUVHK(y7PeDjtXuG`)nP{b3ID%IXo@Gi7;^u#o@EKdrIcJJxGbC|-r{R+aWCA=?p8;2^TW;91~f5)H%HhtVM^ynsKe_bzCKVs#mLDc zTc}AAwzrgnMSB{F3&5CziyHKHd@Di%U*lMxXcq4c&@%0bv)&Er=7YWOIH`sqa$?;s zS0KFVS>DXY$-GqAgq=Tvi-%S@H?a5NvA&yz88ln^49@9Ozk`7d4u7eG+hMv?Cb2(I z%OK@~nzlB+E=(1m*?sN;Sj|k((~tj|j*UQ{O8}U3Ka&J`)Eq4V^+<##B2kvT{c+EJl}fHMS;SmEss2vsDu3Jz^-H#Ca){ zBCrrkvQz?=bof$%)`70T>pFhty8#nvjPDE7+^sg43%WImlY)3mac1L;j~}_!wRg73 z&ADuO=ZCS|Y>S<`b@KG-Qx{B|F}-qL?Mc%rr_QXIURhH+d12+uN%Kyso>4oc`lQJV zw$Zq8>bR+T%k=8%>PeHQRN_6h)s4Vcv$!gL5o}U-7z(f75Wx_l()>Uz7UNM;^YA{- zX*!xKr7Bn+V)?Z>(q7+%5l!X6a2I7#EJ?zql;_%}Q1^1a(8IZrUMTAek%)c6!E-6P zRD-m3LwG|7C(hRL4kqhG3!KZ?ylxh$YhH#2Id}*HgVEfM#oQ`v7h)v$B3Sm~l@-s# zbsb@QCO_IMd>-|9gw~(-Alj(OJa*w&Zc7|7qi<6n9kv+d$&gK36-_*b;w4rTFEG({ z^-6??PwecuN9n8Fg>7B>xj1;?7K;~8%H?u@5^BRro}GtQR4JK%W^;t6A8vA&swO<} zz|wD3R1VKL8;%(GI~-U)#B9GOCbM~MXd1W_6d%j$6<&lVY;l9ag@>Csn=@t zm~v!flOw=-_^UC}res%QNso6<7utE{yEd5mutT>GL6DQZ#I~N`F~VdSd(Ee!M_K5b2q`VNrOX*RrMyTm@yX9K4kl{1xU zI=cBgc&;L%!ZY#h;#T}d@!io5D#CYeqxc3YHkH7d@QC1CA{+_x!DOWBzIWUK3QMy`B6J~gOC9R}ry7@_MD{BCfbCUQ zi_ZVCm1m+x_`;fKTLmi{(bl4I>HpNq`S3>wv67-~R0C{okoK_fN3(G(u6@Hbp;DZ9 zgMu%S0b?&Ogbr@|TCuDV--l=4w&2etuw=8eFnhiYc@U{X+aYbY%PPJofDRh6S@Lo2 zg`yvSv^n2tN4>~#*z>P@%JQRl`M)j@TLkJpSN83I2M3>h+XwQ_es+YBZ3z&BrMe>St?C z%Jb;Dr7ykG)?-VqM7d4S$(E`Zb+lA|GXCeG4tDS38gZK@Bant9_1aNMg~yIs>L(5o zd53Web5yNFx!kL5>nJ~lmgdr1rJYwnY72XLSYMy2IHr`5LwVcLZ&M;cagW+lGTD*_ zvWM73`Tw+cHL-CV*}1xB$Z1mK zh}{%zDdtE`N{Z=3q)3UBMXzX)E7B5SQ8G;^FMb6NYAOP2Y*di|z*nmy)-u)PklqGsyv z)vNbjy?XVks;3Ke*6=Qf*j_?=duG7llGRksKhqYzjMxQ0b5xt7^&lo~`_fK4tC(l% z!ON)SJh=+mVD;MPVHIA+yDqG~elokBId~3GbGR!v#M=s|p;Iq_L-Kh6{7y;TLWuW# zV0P^aF*?r!o+UFDX5N^0E}%uq=WN6i=OJ1*?NynnX^klZ&bgdlSD}~m5F~yNA*~2Ppsm91bnwmIB;PlYYgz_ClhxZ%+NauCUfY-h z2I|!WD5I?_Tif;k?=<2c+e%ZJy##p|81z5%Mh*U2i&DNCj%eGbR zmx%Aqe!PX})fzcF2b27uP(u^JfjIS;NmPriTVHkarpV{(McHMZjJMbnKOjk4vvt?3{Bnrf16P6}_i; z{0dhxYuQ=3hqHss*~k~qUrn2V{}enT+wEq1x^{QbFk>Y0E|mk>&=rdpdGb6laT*;seM?r zM`;zSK)Xnoh@w?(gBCzr;5d`j3hf*1&f8`PYnN>M^R_u=%V<-xt-Rnn&NuBGn1(*R z0WN6`X)SB1GNZKBXTk9tG?bQGdH*^jF^3#lu}ik}BI;772{!{@cgD(&enAND>NY}p z_og(5QneMFfhlEe*SyX-O!S9(MSo1{(dvj-PFVH|G2>0ike#ecWK>eRvg#vG)G^M3 zDz~`p0poNofL3XL0J>s5{G(}pr5~&U1S zb3zT}T9P(JG{kJYS1Sy<4M_kF(HkI12A~*^`%pc`z5sC@T-ZY57V&jm0NYp4x=i1f zL`X1X?3AoUES)wEPfpuhP|}nn++nm?J0(tmJE{R5l*PB54yPtii<7&W&mFbYqUO-N zeI8P#Qj#v2?9&F0B^+M$jU#E1zQBGxAZra|h@nQsOS@mrE;{C10>I__S{5BLRM!DP zo)uQ8iPHw$a5!TEA2}DrNQJsUI-RO>M3<5LRBN?x0l~@JjL;M_)=2$oE!1DMOFMIQ zE{bK!E>uS=_uz)GH9W0|9P6y#owMm= z`$>2)iwZ3iCCk(JIAL?)rH<0`;QUl%?5RP|8|TeF@DNkPX`kA69~T}|H)v+de68>n zJbf_vbj8F}5hB)1wxdp=OrWw&L5DEn^gyyzrJF9)3R=hF;`K%(5yRJ)MG~f##$U6v z-!RVUJ{WbH-Q$=z8|5U%YYt}d!X78Dl+U6uYmM+zTci zKnn6fBOFRij>x2R>T{aa(iRabhRj zB{7?)vv?BzYv9%!;Y{V0tXZGKt*vb7z3H9smqmp+oW&>Izp{15Y2{&A8tT7vt@<2p zg{rLme!d&z}Nw0*kqVI!T#-7l`0xreQLA8VLeb-gYVt~v=>(6N!PFOrxn zc6N+EWBS?n(>}~T+(3NY&NyN(WlrG?BwiCY3~Ohk7=nz@>qzF%U*N)1@@Ua(iRi=P zsUM%ghOK?fl9SmJA}YIdeYNq9kOj-*2ptz0ys{I0is|FQ*B~TIsmTTnXLwpS9E7DT z1sB#l65;I4o}kyn)rHyk<3^ZFR?(%(XX#ebRmsw>EONMKvDG=@K1EC}+?*?YmKC1M zQLX4=(9IKfhb+?B&vtWI<0d|@+45SvX_J$rkW(CXriLe~Sx&K$TaVie?3F+)+OLyAJKFjekDOZ_}K2P7c zmsrM0>{-NV{OUQ&T)J^NsWq}Rsum|TNukA7vA4OCb04m<=|7z+PY=Wz=#-g|mgwYD zBcK!IM(7X0sn%$OlO%MK7qh#TcGF3|?qdO>{9?Iz_M**`{YXlc+X~zjqGGB_#_%G~ z3_MPZJ*LN8X#{%=&t)H-t~=-fSwM5yrme+rW;YiM)VN45o|5Gv&jNH=p?g3k!$s9H zU2J}qeTs*P@Ls>Aw3A~N)4CGls=ru@X`{(LfvuE5Yq}?}C87rWgw2EL?nzR^oib_} z&-@jOS>&m<=CXfff0rEdyj;c+M=rM(DDCYqZsBs{y*^7|KPnGp%&k|@6ba%t4Yv@W zhYB(eCP`X$T*g&t!{`Y_Aw+Uy^|}+cF4@^lr~E7oT@W=`@Y?+3PWM*g^yW*=zSsBE2Zk^r9%o3$8I%&zv?QAyj$&X&33 z4q~yR#&bA2=UUF~2A-@nx&%+QZ=OzyWC>#6(?a4-iUo}vwwpk;R64oG#j=?u!b zX_o&lbDW&C>cCB(xSEojRmdqrd`=69!!T4zy({%>@5T7Bf$=314_g+ct&Lj^) zXl3LWGdBE{*$XegI!|5Yub}| zO?wirJmRBA)OgSfkNhOpl?D&hr0^b2uPS8*B3&}MbN}7En1<59RckJ326$Y`o{{0S zb?|YQd#h~4v6Pi$a+Oyj+XI~9W$_a)eR!HA3m={qNICbzWoaZ2sYK;Zrx#Q@-=?^| zxOFKO^GkW_NTSoz0LRlx*Ad8uYkXOT#ETGJg0NH;AovLw;JExqE$|_RU*5IoSw=J}hC{lm3mt zqi8(u5}(ElrRfmL^#Kjhog^*hskoiBNPnmsv}I=Fw;Dl5r1v2fJwOqkQ`T2JF+K+0 zR6J9ZwFYk3;m9B8Y>mevfeR{6vsjSL4BpQ7fpAxn+g^_O{yE0%o+jPc#cOE4-2~+y4=dH~FEhRinbqeDx^}Tfc8fy(r9}Nd7 z;}p-@I>F09Idi$m$!UXJ$|N9b;a^5gc~U{9S93+UnzpcIlun{%{M;sGLG1Kw#XF9j z43U96dcfY19i6vC_hvsYyrk9|CG*C|OF#eaU;f_o9~^!E&kKL&4H)mwes$sUzTqE! zv(VfXJmUnO+g!{wm+%SNnnK43+HmQbQ}j$O@QTG!vB?0YSO{|tQ}`8u(-gW+_g)L@ zwS>8#Kk$N~Zkz50mOZH91bYzMYh!y6>$b6O#6lYj5j$jKhY;(tu|C`==Xk$<>@epwt z!I$x83FXhS!X;bbQWKOuxQgrSg2AA@5au1P&GmpbxXKP`#|4T(dk(iK;^X1tA_Mi2 zd#MTc%LP}7%D1R|FEo~yYgGoXX%@JTcphU@!-3z7{`5Q-ZTQ6Idwo%5jf@dsMN(uEOmoLs)OfQ$YoY4wUUrqu0I=0?y~JloLI(#60X*>WR6FD35Z}3 zC`&ESM}Z{rQY$HvG-Oz$4Dn@xvTdo1s6WN1KjlGe!LsMIwS-L)Y1zR9cSC)w$^wnp6m@azU_JtF0gBy;uvWPP01f^4nYEx7JQDO z4gk?oFzLBS1mjezaf(`SfZ>sRGr*BO#)ijRaW7(2NCAvA^${t>Fa|Pk2^kk;j)VBd z>AZssw&!pB2$w4c8=uPmwhkw^-*oK9J&5~Fz7;m5rH~KW_~)X}iltm0s#9zYb0ydm z&#ySU3QeVA;FWT&wM0}WH{b|zyK@D{jZ77DJ58Z0sGy@gC|4(FMZD8c6Yz~OS}b-H znj(ncmtfvX-OU9zSO7K?B<_MhD?V1v&lnD9^#)(_A%MV zKewsi1eJD(gndAZ(Nu6<#$5~-8ERg>09D=90k*9f*>7^KPItb5B)Z2fb^yS|fGjxR z-2|0=PqFjR|2*&qzxGv56elUb@>eV$D z>gzPO+Vb5UVnJELa%#`GN{M*LhP8O6%dad$O*@?y8;f&qRdXXd7Xk?56!(TUw{;bA z0GEPlJ?cY|k}gvSFnzAm)~!`N3c0@{T_#HSzFn5(A%^8N2;Q1aJ@+<$atI!NdfC8YP z#Q(`!$jUzh-Co<$zrcAim@%Z*50HnE{fO#M8B`ttDT*ubIM@dM!$OqMd}C5V(<fH$tkDXSXDQ7UX-Z4oAeA+}_Cf&#C1@U@Ij%A8 ziXP024PoFg#yUDNpAZhH0OS?&h$HI3KS0NzbHI489#sCv1BDMA;AaPScVni=dBM7i zUVGToJm_GY7h77RNwz4BfGrG=Wmm#m2=^B9wt26J0%k?2fqc7k=vn7ls z+aLmns0j1-q1DQb4-gdnhwWC!?YJMe78bl=8b_zWj6?94Ss;B(%B_w+DkH}qb)SS( zRS}Zv0BJiV9a0<=W2hn+;gDdO@<%ZH`lJ2`P+FI8nf&|w>Vm)S_z(9X$;87_@URDN z2ki|Q4JLO>*K5+N7GREpN>uarS?l`nur;g+;`TecT4N~8j#YqGh&^fqx`!^?U1+j{ zN^_}1$`uu>6PBPI-8oss$DvV`2&ma_+}-Rd>gu=~+{V|mV}5Sn!qj~A-HS(}7YB~L zF+4DW`)Z4OszuSe^7vYZfOW!ZNeI{{9OFm7?8gts`Bov^ZfbCqE`6paaTo5H)#&w! z;rG8AhQ|hnPT<$1jyW`P{rHV%Zww#nzp;E{sekzR(rf*Ti_44sqsNvPkH2<(acSiE z5H1*ZOkrqXkbef2*Ay&XL@>7SZ@+`b;BTG+yEMh;$XweZ%-6ASjWid)ME?kv4Vg1*B4&h@DDaL+p9VK%WZRpIb1 z@OyYOkA3~Sy zfB!h|m_3?6I5^>$PsmjC?}sS=uLQnN++mblHgk9);xcv*Uq)=&{xaoNgctBjmW#IL zU*&)N6YOUou9YP`9pTLE3piGS5e978xr8?1iV_7i|7x3d4n1Gn3dXY`1B18okV4f`ug=xqR8 z=aJ@5GjPoUByF=DQ}u-!afNgq?RvnlxRE>XAQUQ~BtTU?cK~ zX`8gP$?xa%*WNLgjo^YEx3aCpk(O{;z9(&+^zT>s3*6eCN!ROx9724?@o{VngETRI zkZu2MZf-isPsg*bZ}QXgXtUxYkeO)%LVp(`h&@f1Eb6 zU=@#sPh9-gX4Xf`HB=Z)Ynau>XXR-<4Ha)X)N&2AT++$`#?JE3s?Q6RVr(wE& zy|m_U7b;)cp2|Vf+OCF*Z@aX@Z5KXn`;XhM!Ye--YQEB^`P=cIu9r?LJ`J^8@oT90 z3a9zowXg8og^FMCDtx2)T2J9MR6N^-3a@w+zR~=h%0cmKsO_f1bh)OL-mgmgX*zVg zD7|UE(&BYwyUA$|6grC&4==n4izpPD%?)_SA2@6UZ`;O zLanECX#Z(iLxrn{XQ%m!SKIlr+gG}kj)MokziB@gHa8FAqxl*t{O27i{-0L+%1@P! zh=0n!ej>SOxx#nH^i%8SGh?))_ZCGh5nPh;Tqqlk1I4*mdAP@EU)#R ze!ji+)ME5r^$-YF*2a3*@2xzyhP!9Vi);PmTi5TcuC3m<-+z6z{M_PNdEkwq-VoR3 z+`55x?dvguZ4Icxu!?MY32)-XYxZj>;>Lb&xPr5VvEG>ni8t2|EZ(`(dsHysUJJa% zf91w%gY+Ehwe`^U8m@rF?FA2_G;;3Y4a1;wd5Q0H#v8zKfqR2kk1N&?|6)AVdkO9P zsKeXKxWRF(cM+Fg@mA1#z2W*Td1>=l?+x51v>Y*IksQsSMoB+fL;I1Y4`|4HC~0r!PynE(I) literal 55296 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 O_nPs4<^TWSf&ULzEZbH9 diff --git a/StardewModdingAPI/Events.cs b/StardewModdingAPI/Events.cs index d4311ac3..e0cfc9ce 100644 --- a/StardewModdingAPI/Events.cs +++ b/StardewModdingAPI/Events.cs @@ -4,6 +4,8 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using Microsoft.Xna.Framework.Input; +using StardewValley; +using StardewValley.Menus; namespace StardewModdingAPI { @@ -23,6 +25,14 @@ namespace StardewModdingAPI public delegate void KeyStateChanged(Keys key); public static event KeyStateChanged KeyPressed = delegate { }; + public delegate void ClickableMenuChanged(IClickableMenu newMenu); + public static event ClickableMenuChanged MenuChanged = delegate { }; + + public delegate void GameLocationsChanged(List newLocations); + public static event GameLocationsChanged LocationsChanged = delegate { }; + + public delegate void CurrentLocationsChanged(GameLocation newLocation); + public static event CurrentLocationsChanged CurrentLocationChanged = delegate { }; public static void InvokeGameLoaded() { @@ -86,5 +96,20 @@ namespace StardewModdingAPI { KeyPressed.Invoke(key); } + + public static void InvokeMenuChanged(IClickableMenu newMenu) + { + MenuChanged.Invoke(newMenu); + } + + public static void InvokeLocationsChanged(List newLocations) + { + LocationsChanged.Invoke(newLocations); + } + + public static void InvokeCurrentLocationChanged(GameLocation newLocation) + { + CurrentLocationChanged.Invoke(newLocation); + } } } diff --git a/StardewModdingAPI/Extensions.cs b/StardewModdingAPI/Extensions.cs index b960f027..8b99be1c 100644 --- a/StardewModdingAPI/Extensions.cs +++ b/StardewModdingAPI/Extensions.cs @@ -1,4 +1,5 @@ using System; +using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text; @@ -38,5 +39,15 @@ namespace StardewModdingAPI { return Int32.Parse(s); } + + public static int GetHash(this IEnumerable enumerable) + { + string s = string.Empty; + foreach (var v in enumerable) + { + s += v.GetHashCode(); + } + return s.GetHashCode(); + } } } \ No newline at end of file diff --git a/StardewModdingAPI/Inheritance/Menus/SGameMenu.cs b/StardewModdingAPI/Inheritance/Menus/SGameMenu.cs new file mode 100644 index 00000000..8b883fb6 --- /dev/null +++ b/StardewModdingAPI/Inheritance/Menus/SGameMenu.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.Eventing.Reader; +using System.Linq; +using System.Reflection; +using System.Reflection.Emit; +using System.Text; +using System.Threading.Tasks; +using Microsoft.Xna.Framework.Graphics; +using StardewValley; +using StardewValley.Menus; + +namespace StardewModdingAPI.Inheritance.Menus +{ + public class SGameMenu : StardewValley.Menus.GameMenu + { + public GameMenu BaseGameMenu { get; private set; } + + public List tabs + { + get { return (List)GetBaseFieldInfo("tabs").GetValue(BaseGameMenu); } + set { GetBaseFieldInfo("tabs").SetValue(BaseGameMenu, value); } + } + + public List pages + { + get { return (List)GetBaseFieldInfo("pages").GetValue(BaseGameMenu); } + set { GetBaseFieldInfo("pages").SetValue(BaseGameMenu, value); } + } + + public static SGameMenu ConstructFromBaseClass(GameMenu baseClass) + { + SGameMenu s = new SGameMenu(); + s.BaseGameMenu = baseClass; + return s; + } + + public override void receiveRightClick(int x, int y, bool playSound = true) + { + if (pages[currentTab] is InventoryPage) + { + Program.LogInfo("INV SCREEN"); + } + else + { + } + base.receiveRightClick(x, y, playSound); + } + + public static FieldInfo[] GetPrivateFields() + { + return typeof(GameMenu).GetFields(BindingFlags.Instance | BindingFlags.NonPublic); + } + + public static FieldInfo GetBaseFieldInfo(string name) + { + return typeof(GameMenu).GetField(name, BindingFlags.Instance | BindingFlags.NonPublic); + } + } +} diff --git a/StardewModdingAPI/Inheritance/Menus/SInventoryPage.cs b/StardewModdingAPI/Inheritance/Menus/SInventoryPage.cs new file mode 100644 index 00000000..6bcb7662 --- /dev/null +++ b/StardewModdingAPI/Inheritance/Menus/SInventoryPage.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using StardewValley; +using StardewValley.Menus; + +namespace StardewModdingAPI.Inheritance.Menus +{ + public class SInventoryPage : InventoryPage + { + public InventoryPage BaseInventoryPage { get; private set; } + + public static SInventoryPage ConstructFromBaseClass(InventoryPage baseClass) + { + SInventoryPage s = new SInventoryPage(0,0,0,0); + s.BaseInventoryPage = baseClass; + return s; + } + + public SInventoryPage(int x, int y, int width, int height) : base(x, y, width, height) + { + } + } +} diff --git a/StardewModdingAPI/Inheritance/SGame.cs b/StardewModdingAPI/Inheritance/SGame.cs index 895c4d95..6ac78410 100644 --- a/StardewModdingAPI/Inheritance/SGame.cs +++ b/StardewModdingAPI/Inheritance/SGame.cs @@ -1,11 +1,15 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; +using System.Runtime.Serialization; +using System.Runtime.Serialization.Formatters.Binary; using System.Text; using System.Threading.Tasks; using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; using StardewValley; using StardewValley.Menus; @@ -15,9 +19,14 @@ namespace StardewModdingAPI.Inheritance { public class SGame : Game1 { - public static FieldInfo[] StaticFields { get { return Thing(); } } + public static List ModLocations = new List(); + public static SGameLocation CurrentLocation { get; internal set; } + public static Dictionary ModItems { get; private set; } + public const Int32 LowestModItemID = 1000; - public static FieldInfo[] Thing() + public static FieldInfo[] StaticFields { get { return GetStaticFields(); } } + + public static FieldInfo[] GetStaticFields() { return typeof(Game1).GetFields(); } @@ -33,9 +42,15 @@ namespace StardewModdingAPI.Inheritance get { return CurrentlyPressedKeys.Where(x => !PreviouslyPressedKeys.Contains(x)).ToArray(); } } + public int PreviousGameLocations { get; private set; } + public GameLocation PreviousGameLocation { get; private set; } + public IClickableMenu PreviousActiveMenu { get; private set; } + protected override void Initialize() { Program.Log("XNA Initialize"); + ModItems = new Dictionary(); + PreviouslyPressedKeys = new Keys[0]; Events.InvokeInitialize(); base.Initialize(); } @@ -58,12 +73,33 @@ namespace StardewModdingAPI.Inheritance if (KStateNow != KStatePrior) { Events.InvokeKeyboardChanged(KStateNow); + KStatePrior = KStateNow; } + if (Game1.activeClickableMenu != null && Game1.activeClickableMenu != PreviousActiveMenu) + { + Events.InvokeMenuChanged(Game1.activeClickableMenu); + PreviousActiveMenu = Game1.activeClickableMenu; + } + + if (Game1.locations.GetHash() != PreviousGameLocations) + { + Events.InvokeLocationsChanged(Game1.locations); + PreviousGameLocations = Game1.locations.GetHash(); + } + + if (Game1.currentLocation != PreviousGameLocation) + { + Events.InvokeCurrentLocationChanged(Game1.currentLocation); + PreviousGameLocation = Game1.currentLocation; + } + + if (CurrentLocation != null) + CurrentLocation.update(gameTime); + Events.InvokeUpdateTick(); base.Update(gameTime); - KStatePrior = KStateNow; PreviouslyPressedKeys = CurrentlyPressedKeys; } @@ -71,6 +107,63 @@ namespace StardewModdingAPI.Inheritance { Events.InvokeDrawTick(); base.Draw(gameTime); + spriteBatch.Begin(SpriteSortMode.FrontToBack, BlendState.AlphaBlend, SamplerState.PointClamp, (DepthStencilState)null, (RasterizerState)null); + if (CurrentLocation != null) + CurrentLocation.draw(Game1.spriteBatch); + spriteBatch.End(); + } + + public static Int32 RegisterModItem(SObject modItem) + { + if (modItem.HasBeenRegistered) + { + Program.LogError("The item {0} has already been registered with ID {1}", modItem.Name, modItem.RegisteredId); + return modItem.RegisteredId; + } + Int32 newId = LowestModItemID; + if (ModItems.Count > 0) + newId = Math.Max(LowestModItemID, ModItems.OrderBy(x => x.Key).First().Key + 1); + ModItems.Add(newId, modItem); + modItem.HasBeenRegistered = true; + modItem.RegisteredId = newId; + return newId; + } + + public static SObject PullModItemFromDict(Int32 id, bool isIndex) + { + if (isIndex) + { + if (ModItems.ElementAtOrDefault(id).Value != null) + { + return ModItems.ElementAt(id).Value.Clone(); + } + else + { + Program.LogError("ModItem Dictionary does not contain index: " + id); + return null; + } + } + else + { + if (ModItems.ContainsKey(id)) + { + return ModItems[id].Clone(); + } + else + { + Program.LogError("ModItem Dictionary does not contain ID: " + id); + return null; + } + } + } + + public static SGameLocation GetLocationFromName(String name) + { + if (ModLocations.Any(x => x.name == name)) + { + return ModLocations[ModLocations.IndexOf(ModLocations.First(x => x.name == name))]; + } + return null; } } } \ No newline at end of file diff --git a/StardewModdingAPI/Inheritance/SGameLocation.cs b/StardewModdingAPI/Inheritance/SGameLocation.cs new file mode 100644 index 00000000..f4523c21 --- /dev/null +++ b/StardewModdingAPI/Inheritance/SGameLocation.cs @@ -0,0 +1,90 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.Eventing.Reader; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using StardewValley; +using StardewValley.BellsAndWhistles; + +namespace StardewModdingAPI.Inheritance +{ + public class SGameLocation : GameLocation + { + public GameLocation BaseGameLocation { get; private set; } + + public SerializableDictionary ModObjects { get; set; } + + public static SGameLocation ConstructFromBaseClass(GameLocation baseClass) + { + SGameLocation s = new SGameLocation(); + s.BaseGameLocation = baseClass; + s.ModObjects = new SerializableDictionary(); + //s.IsFarm = baseClass.IsFarm; + //s.IsOutdoors = baseClass.IsOutdoors; + //s.LightLevel = baseClass.LightLevel; + //s.Map = baseClass.Map; + //s.objects = baseClass.objects; + //s.temporarySprites = baseClass.temporarySprites; + s.actionObjectForQuestionDialogue = baseClass.actionObjectForQuestionDialogue; + s.characters = baseClass.characters; + s.critters = (List)typeof(GameLocation).GetField("critters", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(baseClass); + s.currentEvent = baseClass.currentEvent; + s.debris = baseClass.debris; + s.doorSprites = baseClass.doorSprites; + s.doors = baseClass.doors; + s.farmers = baseClass.farmers; + s.fishSplashAnimation = baseClass.fishSplashAnimation; + s.fishSplashPoint = baseClass.fishSplashPoint; + s.forceViewportPlayerFollow = baseClass.forceViewportPlayerFollow; + s.ignoreDebrisWeather = baseClass.ignoreDebrisWeather; + s.ignoreLights = baseClass.ignoreLights; + s.ignoreOutdoorLighting = baseClass.ignoreOutdoorLighting; + s.isFarm = baseClass.isFarm; + s.isOutdoors = baseClass.isOutdoors; + s.isStructure = baseClass.isStructure; + s.largeTerrainFeatures = baseClass.largeTerrainFeatures; + s.lastQuestionKey = baseClass.lastQuestionKey; + s.lastTouchActionLocation = baseClass.lastTouchActionLocation; + s.lightGlows = baseClass.lightGlows; + s.map = baseClass.map; + s.name = baseClass.name; + s.numberOfSpawnedObjectsOnMap = baseClass.numberOfSpawnedObjectsOnMap; + s.objects = baseClass.objects; + s.orePanAnimation = baseClass.orePanAnimation; + s.orePanPoint = baseClass.orePanPoint; + s.projectiles = baseClass.projectiles; + s.temporarySprites = baseClass.temporarySprites; + s.terrainFeatures = baseClass.terrainFeatures; + s.uniqueName = baseClass.uniqueName; + s.warps = baseClass.warps; + s.wasUpdated = (bool)typeof(GameLocation).GetField("wasUpdated", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(baseClass); + s.waterAnimationIndex = baseClass.waterAnimationIndex; + s.waterAnimationTimer = baseClass.waterAnimationTimer; + s.waterColor = baseClass.waterColor; + s.waterTileFlip = baseClass.waterTileFlip; + s.waterTiles = baseClass.waterTiles; + return s; + } + + public static List ConvertGameLocations(List baseGameLocations) + { + return baseGameLocations.Select(ConstructFromBaseClass).ToList(); + } + + public virtual void update(GameTime gameTime) + { + } + + public override void draw(SpriteBatch b) + { + foreach (var v in ModObjects) + { + v.Value.draw(b, (int)v.Key.X, (int)v.Key.Y, -999999, 1); + } + } + } +} diff --git a/StardewModdingAPI/Inheritance/SObject.cs b/StardewModdingAPI/Inheritance/SObject.cs new file mode 100644 index 00000000..e05b4f20 --- /dev/null +++ b/StardewModdingAPI/Inheritance/SObject.cs @@ -0,0 +1,188 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using StardewValley; +using StardewValley.Locations; + +namespace StardewModdingAPI.Inheritance +{ + public class SObject : StardewValley.Object + { + public override String Name { get; set; } + public String Description { get; set; } + public Texture2D Texture { get; set; } + public String CategoryName { get; set; } + public Color CategoryColour { get; set; } + public Boolean IsPassable { get; set; } + public Boolean IsPlaceable { get; set; } + public Boolean HasBeenRegistered { get; set; } + public Int32 RegisteredId { get; set; } + + public Int32 MaxStackSize { get; set; } + + public Boolean WallMounted { get; set; } + public Vector2 DrawPosition { get; set; } + + public Boolean FlaggedForPickup { get; set; } + + public SObject() + { + Name = "Modded Item Name"; + Description = "Modded Item Description"; + CategoryName = "Modded Item Category"; + Category = 4163; + CategoryColour = Color.White; + IsPassable = false; + IsPlaceable = false; + boundingBox = new Rectangle(0, 0, 64, 64); + } + + public override string getDescription() + { + return Description; + } + + public override void draw(SpriteBatch spriteBatch, int x, int y, float alpha = 1) + { + if (Texture != null) + spriteBatch.Draw(Texture, new Vector2(x, y), new Color(255, 255, 255, 255f * alpha)); + } + + public override void draw(SpriteBatch spriteBatch, int xNonTile, int yNonTile, float layerDepth, float alpha = 1) + { + if (Texture != null) + { + spriteBatch.Draw(Texture, new Vector2(xNonTile, yNonTile), null, new Color(255, 255, 255, 255f * alpha), 0, Vector2.Zero, 1, SpriteEffects.None, layerDepth); + spriteBatch.DrawString(Game1.dialogueFont, "TARG: " + new Vector2(xNonTile, yNonTile), new Vector2(128, 0), Color.Red); + } + } + + public override void drawInMenu(SpriteBatch spriteBatch, Vector2 location, float scaleSize, float transparency, float layerDepth, bool drawStackNumber) + { + if (this.isRecipe) + { + transparency = 0.5f; + scaleSize *= 0.75f; + } + + if (Texture != null) + { + int targSize = (int) (64 * scaleSize * 0.9f); + int midX = (int) ((location.X) + 32); + int midY = (int) ((location.Y) + 32); + + int targX = midX - targSize / 2; + int targY = midY - targSize / 2; + + spriteBatch.Draw(Texture, new Rectangle(targX, targY, targSize, targSize), null, new Color(255, 255, 255, transparency), 0, Vector2.Zero, SpriteEffects.None, layerDepth); + } + if (drawStackNumber) + { + float scale = 0.5f + scaleSize; + Game1.drawWithBorder(string.Concat(this.stack), Color.Black, Color.White, location + new Vector2((float) Game1.tileSize - Game1.tinyFont.MeasureString(string.Concat(this.stack)).X * scale, (float) Game1.tileSize - (float) ((double) Game1.tinyFont.MeasureString(string.Concat(this.stack)).Y * 3.0f / 4.0f) * scale), 0.0f, scale, 1f, true); + } + } + + public override void drawWhenHeld(SpriteBatch spriteBatch, Vector2 objectPosition, Farmer f) + { + if (Texture != null) + { + int targSize = 64; + int midX = (int) ((objectPosition.X) + 32); + int midY = (int) ((objectPosition.Y) + 32); + + int targX = midX - targSize / 2; + int targY = midY - targSize / 2; + + spriteBatch.Draw(Texture, new Rectangle(targX, targY, targSize, targSize), null, Color.White, 0, Vector2.Zero, SpriteEffects.None, (f.getStandingY() + 2) / 10000f); + } + } + + public override Color getCategoryColor() + { + return CategoryColour; + } + + public override string getCategoryName() + { + if (string.IsNullOrEmpty(CategoryName)) + return "Modded Item"; + return CategoryName; + } + + public override bool isPassable() + { + return IsPassable; + } + + public override bool isPlaceable() + { + return IsPlaceable; + } + + public override int maximumStackSize() + { + return MaxStackSize; + } + + public SObject Clone() + { + SObject toRet = new SObject(); + + toRet.Name = this.Name; + toRet.CategoryName = this.CategoryName; + toRet.Description = this.Description; + toRet.Texture = this.Texture; + toRet.IsPassable = this.IsPassable; + toRet.IsPlaceable = this.IsPlaceable; + toRet.quality = this.quality; + toRet.scale = this.scale; + toRet.isSpawnedObject = this.isSpawnedObject; + toRet.isRecipe = this.isRecipe; + toRet.questItem = this.questItem; + toRet.stack = 1; + toRet.HasBeenRegistered = this.HasBeenRegistered; + toRet.RegisteredId = this.RegisteredId; + + return toRet; + } + + public override Item getOne() + { + return this.Clone(); + } + + public override bool placementAction(GameLocation location, int x, int y, Farmer who = null) + { + SGameLocation s = SGame.GetLocationFromName(location.name); + + if (s.GetHashCode() != SGame.CurrentLocation.GetHashCode()) + { + Program.LogError("HASH DIFFERENCE: " + s.GetHashCode() + " | " + SGame.ModLocations[SGame.ModLocations.IndexOf(SGame.ModLocations.First(z => z.name == location.name))].GetHashCode() + " | " + SGame.CurrentLocation.GetHashCode()); + Console.ReadKey(); + } + + Console.Title = (this.GetHashCode() + " PLACEMENT"); + + if (s != null) + { + Vector2 index1 = new Vector2((float)(x / Game1.tileSize), (float)(y / Game1.tileSize)); + if (!s.ModObjects.ContainsKey(index1)) + { + s.ModObjects.Add(index1, this); + return true; + } + } + else + { + Program.LogError("No SGameLocation could be found for the supplied GameLocation!"); + return false; + } + return false; + } + } +} \ No newline at end of file diff --git a/StardewModdingAPI/Program.cs b/StardewModdingAPI/Program.cs index ff52272c..8109d99f 100644 --- a/StardewModdingAPI/Program.cs +++ b/StardewModdingAPI/Program.cs @@ -4,6 +4,7 @@ using System.ComponentModel; using System.IO; using System.Linq; using System.Reflection; +using System.Reflection.Emit; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -12,6 +13,7 @@ using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; using StardewModdingAPI.Inheritance; +using StardewModdingAPI.Inheritance.Menus; using StardewValley; using StardewValley.Menus; using StardewValley.Minigames; @@ -27,6 +29,7 @@ namespace StardewModdingAPI public static string ExecutionPath { get; private set; } public static string DataPath = Path.Combine(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "StardewValley")); public static string ModPath = Path.Combine(Path.Combine(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "StardewValley")), "Mods"); + public static string ModContentPath = Path.Combine(Path.Combine(Path.Combine(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "StardewValley")), "Mods"), "Content"); public static string LogPath = Path.Combine(Path.Combine(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "StardewValley")), "ErrorLogs"); public static string CurrentLog { get; private set; } public static StreamWriter LogStream { get; private set; } @@ -59,7 +62,9 @@ namespace StardewModdingAPI File.Delete(ModPath); if (!Directory.Exists(ModPath)) Directory.CreateDirectory(ModPath); - + if (!Directory.Exists(ModContentPath)) + Directory.CreateDirectory(ModContentPath); + ExecutionPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); CurrentLog = LogPath + "\\MODDED_ProgramLog_" + System.DateTime.Now.Ticks + ".txt"; @@ -75,10 +80,41 @@ namespace StardewModdingAPI Console.ReadKey(); Environment.Exit(-4); } + StardewAssembly = Assembly.LoadFile(ExecutionPath + "\\Stardew Valley.exe"); StardewProgramType = StardewAssembly.GetType("StardewValley.Program", true); StardewGameInfo = StardewProgramType.GetField("gamePtr"); + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + //HOLY FUCKING SHIT IGNORE THIS I JUST WANTED TO OVERRIDE A NON VIRTUAL METHOD + + + /*int fieldOffset = 0; + foreach (FieldInfo sourceField in sourceFields) + { + FieldBuilder fieldBuilder + = tb.DefineField( + sourceField.Name, + sourceField.FieldType, + FieldAttributes.Public); + fieldBuilder.SetOffset(fieldOffset); + fieldOffset++; + }*/ + + //Type dynamicType = tb.CreateType(); + //System.Object dynObj = Activator.CreateInstance(dynamicType); + + + + /*foreach (FieldInfo sourceField in sourceFields) + { + FieldInfo destField + = dynObj.GetType().GetField(sourceField.Name); + destField.SetValue(dynObj, sourceField.GetValue(sourceObject)); + }*/ + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + LogInfo("Injecting New SDV Version..."); Game1.version += "-Z_MODDED"; @@ -86,21 +122,25 @@ namespace StardewModdingAPI LogInfo("Starting SDV..."); gameThread.Start(); - SGame.Thing(); - + SGame.GetStaticFields(); + while (!ready) { - + } Log("SDV Loaded Into Memory"); consoleInputThread = new Thread(ConsoleInputThread); LogInfo("Initializing Console Input Thread..."); - consoleInputThread.Start(); + RegisterCommands(); Events.KeyPressed += Events_KeyPressed; Events.UpdateTick += Events_UpdateTick; + Events.LoadContent += Events_LoadContent; + //Events.MenuChanged += Events_MenuChanged; + Events.LocationsChanged += Events_LocationsChanged; + Events.CurrentLocationChanged += Events_CurrentLocationChanged; LogInfo("Applying Final SDV Tweaks..."); StardewInvoke(() => @@ -110,9 +150,12 @@ namespace StardewModdingAPI }); LogInfo("Game Loaded"); - LogColour(ConsoleColor.Cyan, "Type 'help' for help, or 'help ' for a command's usage"); Events.InvokeGameLoaded(); + consoleInputThread.Start(); + LogColour(ConsoleColor.Cyan, "Type 'help' for help, or 'help ' for a command's usage"); + + while (ready) { //Check if the game is still running 10 times a second @@ -126,7 +169,7 @@ namespace StardewModdingAPI LogInfo("Shutting Down..."); int time = 0; int step = 100; - int target = 2000; + int target = 1000; while (true) { time += step; @@ -140,7 +183,7 @@ namespace StardewModdingAPI Environment.Exit(0); } - + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -205,14 +248,35 @@ namespace StardewModdingAPI { string input = string.Empty; - RegisterCommands(); - while (true) { Command.CallCommand(Console.ReadLine()); } } + static void Events_LoadContent() + { + LogColour(ConsoleColor.Magenta, "REGISTERING BASE CUSTOM ITEM"); + SObject so = new SObject(); + so.Name = "Mario Block"; + so.CategoryName = "SMAPI Test Mod"; + so.Description = "It's a block from Mario!\nLoaded in realtime by SMAPI."; + so.Texture = Texture2D.FromStream(Game1.graphics.GraphicsDevice, new FileStream(ModContentPath + "\\Test.png", FileMode.Open)); + so.IsPassable = true; + so.IsPlaceable = true; + LogColour(ConsoleColor.Cyan, "REGISTERED WITH ID OF: " + SGame.RegisterModItem(so)); + + LogColour(ConsoleColor.Magenta, "REGISTERING SECOND CUSTOM ITEM"); + SObject so2 = new SObject(); + so2.Name = "Mario Painting"; + so2.CategoryName = "SMAPI Test Mod"; + so2.Description = "It's a painting of a creature from Mario!\nLoaded in realtime by SMAPI."; + so2.Texture = Texture2D.FromStream(Game1.graphics.GraphicsDevice, new FileStream(ModContentPath + "\\PaintingTest.png", FileMode.Open)); + so2.IsPassable = true; + so2.IsPlaceable = true; + LogColour(ConsoleColor.Cyan, "REGISTERED WITH ID OF: " + SGame.RegisterModItem(so2)); + } + static void Events_KeyPressed(Keys key) { @@ -238,6 +302,27 @@ namespace StardewModdingAPI } } + static void Events_MenuChanged(IClickableMenu newMenu) + { + LogInfo("NEW MENU: " + newMenu.GetType()); + if (newMenu is GameMenu) + { + Game1.activeClickableMenu = SGameMenu.ConstructFromBaseClass(Game1.activeClickableMenu as GameMenu); + } + } + + static void Events_LocationsChanged(List newLocations) + { + SGame.ModLocations = SGameLocation.ConvertGameLocations(Game1.locations); + } + + static void Events_CurrentLocationChanged(GameLocation newLocation) + { + SGame.CurrentLocation = null; + System.Threading.Thread.Sleep(10); + SGame.CurrentLocation = SGame.ModLocations.First(x => x.name == newLocation.name); + } + public static void StardewInvoke(Action a) { StardewForm.Invoke(a); @@ -270,6 +355,7 @@ namespace StardewModdingAPI Command.RegisterCommand("show", "Shows the game form | show").CommandFired += show_CommandFired; Command.RegisterCommand("save", "Saves the game? Doesn't seem to work. | save").CommandFired += save_CommandFired; + Command.RegisterCommand("load", "Shows the load screen | load").CommandFired += load_CommandFired; Command.RegisterCommand("exit", "Closes the game | exit").CommandFired += exit_CommandFired; Command.RegisterCommand("stop", "Closes the game | stop").CommandFired += exit_CommandFired; @@ -292,6 +378,7 @@ namespace StardewModdingAPI Command.RegisterCommand("out_items", "Outputs a list of items | out_items", new[] { "" }).CommandFired += out_items; Command.RegisterCommand("out_melee", "Outputs a list of melee weapons | out_melee", new[] { "" }).CommandFired += out_melee; + Command.RegisterCommand("newitem", "Outputs a list of melee weapons | out_melee", new[] { "" }).CommandFired += RegisterNewItem; Command.RegisterCommand("world_settime", "Sets the time to the specified value | world_settime ", new[] { "(Int32) The target time [06:00 AM is 600]" }).CommandFired += world_setTime; Command.RegisterCommand("world_freezetime", "Freezes or thaws time | world_freezetime ", new[] { "(0 - 1) Whether or not to freeze time. 0 is thawed, 1 is frozen" }).CommandFired += world_freezeTime; @@ -340,6 +427,11 @@ namespace StardewModdingAPI StardewValley.SaveGame.Save(); } + static void load_CommandFired(Command cmd) + { + Game1.activeClickableMenu = new StardewValley.Menus.LoadGameMenu(); + } + static void exit_CommandFired(Command cmd) { Application.Exit(); @@ -857,7 +949,8 @@ namespace StardewModdingAPI try { Item it = new StardewValley.Object(i, 1); - Console.WriteLine(i + "| " + it.Name); + if (it.Name != "Error Item") + Console.WriteLine(i + "| " + it.Name); } catch { @@ -902,6 +995,11 @@ namespace StardewModdingAPI static void blank_command(Command cmd) { } + static void RegisterNewItem(Command cmd) + { + Game1.player.addItemToInventory(SGame.PullModItemFromDict(0, true)); + } + #endregion diff --git a/StardewModdingAPI/StardewModdingAPI.csproj b/StardewModdingAPI/StardewModdingAPI.csproj index a6815f26..42c604a2 100644 --- a/StardewModdingAPI/StardewModdingAPI.csproj +++ b/StardewModdingAPI/StardewModdingAPI.csproj @@ -47,6 +47,7 @@ icon.ico + @@ -64,13 +65,21 @@ + + False + D:\#Network-Steam\SteamRepo\steamapps\common\Stardew Valley\xTile.dll + + + + + diff --git a/StardewModdingAPI/obj/x86/Debug/StardewModdingAPI.csproj.FileListAbsolute.txt b/StardewModdingAPI/obj/x86/Debug/StardewModdingAPI.csproj.FileListAbsolute.txt index 709d649c..83b3576c 100644 --- a/StardewModdingAPI/obj/x86/Debug/StardewModdingAPI.csproj.FileListAbsolute.txt +++ b/StardewModdingAPI/obj/x86/Debug/StardewModdingAPI.csproj.FileListAbsolute.txt @@ -33,3 +33,4 @@ C:\TFSource\Master-Collection\StardewModdingAPI\StardewModdingAPI\bin\x86\Debug\ C:\TFSource\Master-Collection\StardewModdingAPI\StardewModdingAPI\obj\x86\Debug\StardewModdingAPI.exe C:\TFSource\Master-Collection\StardewModdingAPI\StardewModdingAPI\obj\x86\Debug\StardewModdingAPI.pdb C:\TFSource\Master-Collection\StardewModdingAPI\StardewModdingAPI\obj\x86\Debug\StardewModdingAPI.csprojResolveAssemblyReference.cache +C:\TFSource\Master-Collection\StardewModdingAPI\StardewModdingAPI\bin\x86\Debug\Microsoft.QualityTools.Testing.Fakes.dll diff --git a/Vanilla Items List.txt b/Vanilla Items List.txt new file mode 100644 index 00000000..f19ae547 --- /dev/null +++ b/Vanilla Items List.txt @@ -0,0 +1,538 @@ +0| Weeds +2| Stone +4| Stone +16| Wild Horseradish +18| Daffodil +20| Leek +22| Dandelion +24| Parsnip +30| Lumber +60| Emerald +62| Aquamarine +64| Ruby +66| Amethyst +68| Topaz +70| Jade +72| Diamond +74| Prismatic Shard +78| Cave Carrot +80| Quartz +82| Fire Quartz +84| Frozen Tear +86| Earth Crystal +88| Coconut +90| Cactus Fruit +92| Sap +96| Dwarf Scroll I +97| Dwarf Scroll II +98| Dwarf Scroll III +99| Dwarf Scroll IV +100| Chipped Amphora +101| Arrowhead +102| Lost Book +103| Ancient Doll +104| Elvish Jewelry +105| Chewing Stick +106| Ornamental Fan +107| Dinosaur Egg +108| Rare Disc +109| Ancient Sword +110| Rusty Spoon +111| Rusty Spur +112| Rusty Cog +113| Chicken Statue +114| Ancient Seed +115| Prehistoric Tool +116| Dried Starfish +117| Anchor +118| Glass Shards +119| Bone Flute +120| Prehistoric Handaxe +121| Dwarvish Helm +122| Dwarf Gadget +123| Ancient Drum +124| Golden Mask +125| Golden Relic +126| Strange Doll +127| Strange Doll +128| Pufferfish +129| Anchovy +130| Tuna +131| Sardine +132| Bream +136| Largemouth Bass +137| Smallmouth Bass +138| Rainbow Trout +139| Salmon +140| Walleye +141| Perch +142| Carp +143| Catfish +144| Pike +145| Sunfish +146| Red Mullet +147| Herring +148| Eel +149| Octopus +150| Red Snapper +151| Squid +152| Seaweed +153| Green Algae +154| Sea Cucumber +155| Super Cucumber +156| Ghostfish +157| White Algae +158| Stonefish +159| Crimsonfish +160| Angler +161| Ice Pip +162| Lava Eel +163| Legend +164| Sandfish +165| Scorpion Carp +166| Treasure Chest +167| Joja Cola +168| Trash +169| Driftwood +170| Broken Glasses +171| Broken CD +172| Soggy Newspaper +174| Large Egg +176| Egg +178| Hay +180| Egg +182| Large Egg +184| Milk +186| Large Milk +188| Green Bean +190| Cauliflower +192| Potato +194| Fried Egg +195| Omelet +196| Salad +197| Cheese Cauliflower +198| Baked Fish +199| Parsnip Soup +200| Vegetable Medley +201| Complete Breakfast +202| Fried Calamari +203| Strange Bun +204| Lucky Lunch +205| Fried Mushroom +206| Pizza +207| Bean Hotpot +208| Glazed Yams +209| Carp Surprise +210| Hashbrowns +211| Pancakes +212| Salmon Dinner +213| Fish Taco +214| Crispy Bass +215| Pepper Poppers +216| Bread +218| Tom Kha Soup +219| Trout Soup +220| Chocolate Cake +221| Pink Cake +222| Rhubarb Pie +223| Cookie +224| Spaghetti +225| Fried Eel +226| Spicy Eel +227| Sashimi +228| Maki Roll +229| Tortilla +230| Red Plate +231| Eggplant Parmesan +232| Rice Pudding +233| Ice Cream +234| Blueberry Tart +235| Autumn's Bounty +236| Pumpkin Soup +237| Super Meal +238| Cranberry Sauce +239| Stuffing +240| Farmer's Lunch +241| Survival Burger +242| Dish O' The Sea +243| Miner's Treat +244| Roots Platter +245| Sugar +246| Wheat Flour +247| Oil +248| Garlic +250| Kale +252| Rhubarb +254| Melon +256| Tomato +257| Morel +258| Blueberry +259| Fiddlehead Fern +260| Hot Pepper +262| Wheat +264| Radish +266| Red Cabbage +268| Starfruit +270| Corn +272| Eggplant +274| Artichoke +276| Pumpkin +278| Bok Choy +280| Yam +281| Chanterelle +282| Cranberries +283| Holly +284| Beet +286| Cherry Bomb +287| Bomb +288| Mega Bomb +290| Stone +294| Twig +295| Twig +296| Salmonberry +297| Grass Starter +298| Hardwood Fence +299| Amaranth Seeds +300| Amaranth +301| Grape Starter +302| Hops Starter +303| Pale Ale +304| Hops +305| Void Egg +306| Mayonnaise +307| Duck Mayonnaise +309| Acorn +310| Maple Seed +311| Pine Cone +313| Weeds +314| Weeds +315| Weeds +316| Weeds +317| Weeds +318| Weeds +319| Weeds +320| Weeds +321| Weeds +322| Wood Fence +323| Stone Fence +324| Iron Fence +325| Gate +326| Dwarvish Translation Guide +328| Wood Floor +329| Stone Floor +330| Clay +331| Weathered Floor +333| Crystal Floor +334| Copper Bar +335| Iron Bar +336| Gold Bar +337| Iridium Bar +338| Refined Quartz +340| Honey +341| Tea Set +342| Pickles +343| Stone +344| Jelly +346| Beer +347| Rare Seed +348| Wine +349| Energy Tonic +350| Juice +351| Muscle Remedy +368| Basic Fertilizer +369| Quality Fertilizer +370| Basic Retaining Soil +371| Quality Retaining Soil +372| Clam +373| Golden Pumpkin +376| Poppy +378| Copper Ore +380| Iron Ore +382| Coal +384| Gold Ore +386| Iridium Ore +388| Wood +390| Stone +392| Nautilus Shell +393| Coral +394| Rainbow Shell +395| Coffee +396| Spice Berry +397| Sea Urchin +398| Grape +399| Spring Onion +400| Strawberry +401| Straw Floor +402| Sweet Pea +403| Field Snack +404| Common Mushroom +405| Wood Path +406| Wild Plum +407| Gravel Path +408| Hazelnut +409| Crystal Path +410| Blackberry +411| Cobblestone Path +412| Winter Root +413| Blue Slime Egg +414| Crystal Fruit +416| Snow Yam +417| Sweet Gem Berry +418| Crocus +419| Vinegar +420| Red Mushroom +421| Sunflower +422| Purple Mushroom +423| Rice +424| Cheese +425| Fairy Seeds +426| Goat Cheese +427| Tulip Bulb +428| Cloth +429| Jazz Seeds +430| Truffle +431| Sunflower Seeds +432| Truffle Oil +434| Stardrop +436| Goat Milk +437| Red Slime Egg +438| L. Goat Milk +439| Purple Slime Egg +440| Wool +441| Explosive Ammo +442| Duck Egg +444| Duck Feather +446| Rabbit's Foot +449| Stone Base +450| Stone +452| Weeds +453| Poppy Seeds +454| Ancient Fruit +455| Spangle Seeds +456| Algae Soup +457| Pale Broth +458| Bouquet +460| Mermaid's Pendant +461| Decorative Pot +463| Drum Block +464| Flute Block +465| Speed-Gro +466| Deluxe Speed-Gro +472| Parsnip Seeds +473| Bean Starter +474| Cauliflower Seeds +475| Potato Seeds +476| Garlic Seeds +477| Kale Seeds +478| Rhubarb Seeds +479| Melon Seeds +480| Tomato Seeds +481| Blueberry Seeds +482| Pepper Seeds +483| Wheat Seeds +484| Radish Seeds +485| Red Cabbage Seeds +486| Starfruit Seeds +487| Corn Seeds +488| Eggplant Seeds +489| Artichoke Seeds +490| Pumpkin Seeds +491| Bok Choy Seeds +492| Yam Seeds +493| Cranberry Seeds +494| Beet Seeds +495| Spring Seeds +496| Summer Seeds +497| Fall Seeds +498| Winter Seeds +499| Ancient Seeds +516| Small Glow Ring +517| Glow Ring +518| Small Magnet Ring +519| Magnet Ring +520| Slime Charmer Ring +521| Warrior Ring +522| Vampire Ring +523| Savage Ring +524| Ring of Yoba +525| Sturdy Ring +526| Burglar's Ring +527| Iridium Band +528| Jukebox Ring +529| Amethyst Ring +530| Topaz Ring +531| Aquamarine Ring +532| Jade Ring +533| Emerald Ring +534| Ruby Ring +535| Geode +536| Frozen Geode +537| Magma Geode +538| Alamite +539| Bixite +540| Baryte +541| Aerinite +542| Calcite +543| Dolomite +544| Esperite +545| Fluorapatite +546| Geminite +547| Helvite +548| Jamborite +549| Jagoite +550| Kyanite +551| Lunarite +552| Malachite +553| Neptunite +554| Lemon Stone +555| Nekoite +556| Orpiment +557| Petrified Slime +558| Thunder Egg +559| Pyrite +560| Ocean Stone +561| Ghost Crystal +562| Tigerseye +563| Jasper +564| Opal +565| Fire Opal +566| Celestine +567| Marble +568| Sandstone +569| Granite +570| Basalt +571| Limestone +572| Soapstone +573| Hematite +574| Mudstone +575| Obsidian +576| Slate +577| Fairy Stone +578| Star Shards +579| Prehistoric Scapula +580| Prehistoric Tibia +581| Prehistoric Skull +582| Skeletal Hand +583| Prehistoric Rib +584| Prehistoric Vertebra +585| Skeletal Tail +586| Nautilus Shell +587| Amphibian Fossil +588| Palm Fossil +589| Trilobite +590| Artifact Spot +591| Tulip +593| Summer Spangle +595| Fairy Rose +597| Blue Jazz +599| Sprinkler +604| Plum Pudding +605| Artichoke Dip +606| Stir Fry +607| Roasted Hazelnuts +608| Pumpkin Pie +609| Radish Salad +610| Fruit Salad +611| Blackberry Cobbler +612| Cranberry Candy +613| Apple +618| Bruschetta +621| Quality Sprinkler +628| Cherry Sapling +629| Apricot Sapling +630| Orange Sapling +631| Peach Sapling +632| Pomegranate Sapling +633| Apple Sapling +634| Apricot +635| Orange +636| Peach +637| Pomegranate +638| Cherry +645| Iridium Sprinkler +648| Coleslaw +649| Fiddlehead Risotto +651| Poppyseed Muffin +668| Stone +670| Stone +674| Weeds +675| Weeds +676| Weeds +677| Weeds +678| Weeds +679| Weeds +680| Green Slime Egg +681| Rain Totem +682| Mutant Carp +684| Bug Meat +685| Bait +686| Spinner +687| Dressed Spinner +688| Warp Totem: Farm +689| Warp Totem: Mountains +690| Warp Totem: Beach +691| Barbed Hook +692| Lead Bobber +693| Treasure Hunter +694| Trap Bobber +695| Cork Bobber +698| Sturgeon +699| Tiger Trout +700| Bullhead +701| Tilapia +702| Chub +703| Magnet +704| Dorado +705| Albacore +706| Shad +707| Lingcod +708| Halibut +709| Hardwood +710| Crab Pot +715| Lobster +716| Crayfish +717| Crab +718| Cockle +719| Mussel +720| Shrimp +721| Snail +722| Periwinkle +723| Oyster +724| Maple Syrup +725| Oak Resin +726| Pine Tar +727| Chowder +728| Fish Stew +729| Escargot +730| Lobster Bisque +731| Maple Bar +732| Crab Cakes +734| Woodskip +745| Strawberry Seeds +746| Jack-O-Lantern +747| Rotten Plant +748| Rotten Plant +749| Omni Geode +750| Weeds +751| Stone +760| Stone +762| Stone +764| Stone +765| Stone +766| Slime +767| Bat Wing +768| Solar Essence +769| Void Essence +770| Mixed Seeds +771| Fiber +772| Oil of Garlic +773| Life Elixir +774| Wild Bait +775| Glacierfish +784| Weeds +785| Weeds +786| Weeds +787| Battery Pack +788| Lost Axe +789| Lucky Purple Shorts +790| Berry Basket \ No newline at end of file