From c63580dbb865cd25369d39821cabf7f178a9330f Mon Sep 17 00:00:00 2001 From: JustinAJ Date: Sat, 30 May 2015 12:08:24 -0400 Subject: [PATCH] Added RenX::BuildingInfo struct, and all appropriate functions and config settings. Improved tags. Moved RenX::Core initialization away from constructor to load(). --- Release/Plugins/RenX.Core.lib | Bin 125108 -> 128188 bytes RenX.Core/RenX.Core.vcxproj | 1 + RenX.Core/RenX.Core.vcxproj.filters | 3 + RenX.Core/RenX_BuildingInfo.h | 59 ++++++++++ RenX.Core/RenX_Core.cpp | 22 ++-- RenX.Core/RenX_Core.h | 6 +- RenX.Core/RenX_Functions.cpp | 4 +- RenX.Core/RenX_Server.cpp | 128 +++++++++++++++++---- RenX.Core/RenX_Server.h | 20 ++++ RenX.Core/RenX_Tags.cpp | 166 +++++++++++++++------------- 10 files changed, 294 insertions(+), 115 deletions(-) create mode 100644 RenX.Core/RenX_BuildingInfo.h diff --git a/Release/Plugins/RenX.Core.lib b/Release/Plugins/RenX.Core.lib index 351b3936676306f6f40d344e3171eabd4a7855e0..3ec45f8da12fb4c13b4e967e2ba1f86cda36aa89 100644 GIT binary patch delta 16982 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 XT-JH6sfA5{F04G54b+M|T;aa~ALkIo delta 15642 zcmb_i2Y6J~*4-QFAcWpY=onh)p`}0w#Xv&uB%zm>gkEI=BGN$ya!~0=Z-F2nAcP{l zgd)9*fQS&$=kwY4*FN_$xpy+Y_kO>}_bqN_&bqswea=01_J5mg=Y?$ZOJu9npkCeD zwdy!imK1i>ZcwvsO&|Fem6Iq_FmbIZ#C3KO*L_C(_F>{ydx@7!BVO!<&kc!N2N4II zFi;=kf{mLEY>FZl9NJ@G3E^H~QIdhj5yXN=#|)fy;O5gn%f<$p)FKuvTx*~?lnVSY zF4+Fuz`~Lk2SR2VsNWQZ0L|wb2rW%4Xy9uC4mALRcNu61Spr83DARz&Er3QK2panv zXqrSUXpAwzlePvPKZGa1y{85ehY$H*Xt>|NBzPhi6JVf2XJWyeB?kH*AQp5>H83nIv7pB} z1HEt+^c-)X7n~FfLn;L$_8M@E$c;aM;RuIdZfgVcju8vyPctz0XM7Jtco}Gqsuo1R zU_ray2Hu@SEcmdcfrOI8f~mh7=$k?;=$~K1!7-ajqhoerLHkt(x0{@fqugcyf=kdFg3`)*d@e*8E`@nj(fw0ApfHwR4~QIz>M}F0Fy2o zn1Z|sx*!sQk+@ONqpE?4m=%H#;H6+zgn`b*i3OAU8JK;8Sfe1WfMYZu|9uE+1n=}Q z&^3%$Fbeq-bcS$2WLXn0aRs7M4Mfi*7Q{_55Z{_uFs-+Nf!BxygJ8U%4)xbb_Cy2>y;DZN<05A%l1+j+>jDsP9*op=^ z?nJ7AgjCFb{KpfJHw`GA0E}O6V8MQ3fpffpX1>INCa3{H7@`vvitkn!ID*fDfD
    @aO!}DgO4Cgg2Q_ae1k#3Su$|G zD?$a_{mH;b4~Yd26Ahe!v4UHf4SWhC1>e9J!OA`cF3cy^$b&2JQ5^yDzZil9tB_~G z%0~uHAyk5s@KUh)nF&N|HSpO^13UjD)(FEDNQP&EE9(th&x)D=t_?77`8gIe;5gEJ z+=2g&UNLY21dTLYfiLeEI0o+o$Ki?K814~#+1o(d7-9_wZ42B7N6-@C7PLZi1%cpe zpdbT*kix_j<-eeg2JQ{VYIxYdIbX~OAZ3yuc}WicY{{APb)nAR@D{mt>&pXvE_rjqzPGlZ#WeRj}X43rLK@@)Xc zz^-5r8{)fUXDWLUh5^6s zWg39bvA9lGOr0-7A!P4@5xyJ15uJ-1OzqoXAc<+}R;C@>nDQ@W>b`}k>LsSko0&q7 zGS&N82Tlbk3tYIn-&v#&K_5r3RUoair4`sL>hOEPg(6t*(Il-$3qZ`A4{cy;4 z5>vn!7}9}h$sDEw{h3l7-I%ftV>;IZ=*2X?CluqFgzxr_V9E`2AI{WzF2XtwshH37 zGye99K*-xeFs{AZF->}xspW?VZ35HpQ<+lw!VxIg9K)2oBhxByCv|6v>BO{bCezmU z5xoISj*!7jX~6J)OjF)NesS}Xu~0Gtgm92YGxVMkU^JrpGmPr<4pUfHI5-M?aLPt9y#!LDkpG#{uq+N9#>10o z2;D#^7{nCPhba@h=+_&?h_HnXg<(Sw{^<~osQo$)3c<|{4r_M|Z36BE){jTD79he-q@o!j&;$mB!NSlmrWN?&+!0iE0CEdd-UFeifyRen*dus! z4)yT~3U37}_bgIz6$S#?ufW)^P@u^7uIu361@|`O9K`o`;LLd_OlA5d5%Ru9F|I?g zu4TFdbleV(V+X4L5JH@cX|e$pC!rWoOw0Bm$GhR_HWUp6o`OM9HxV`nSaA!5hq0F* zGsOd;%Ta*KP*^bT8vgdj-}{&1iYa*D6pVsnd*O)xH>epH-xWsv1VbNwg#0Hygy1u% zbP@U~1cB6NCDZ&1OnHDhASEt_*Q=Nw;d?I#j6aE#tcGF0&d-?s+=&na2jIkdL?kOB zG2j}e<7Ie#oaxF@d_I9x0C&EGzGKjV?;jjP{(Iw#n6@ATeeT2Zmaw=L@)(Fv0);~m zsvs2TJ>>Tia)(q*N?{7lL{yS;QBi6@-sD4NsWWw=3RICQQz6<*DRhv^a9J+TImw^O zP)DjnpVJpqj!RGxDn+HK5tSoHc`8WW?87Cw6u(D9D2Cplp){Jh(J0zMV`&~OrWuq- z8>lCZp;^?Mq9~do=~McMKBiA-39X{lG@K^U2PLNPCT%4}Q>m+i*3e{1qK&kRKBJv9n_{U8eLzl%r(~K>@6&X0Py!93 z@wA-g&=y)x(`X8fqq($zKBVq6fCke*8boolkap7^Do%x|F?mr{`ikmNW`2WzrSIq| z9izMyOg~T>eNWHm1wE(ZguO>r&cZo42meVOs1;qK>vWYKQ#EQxcc?YxrZ*{s-lnE> zm;&i*3ZekIOE;((-K5);hu`GfoQrGF1NxQ@(Kl3w{HQL~ru%e{+EO^Rp)jgW7pOAd zqC9kj{y{&{0cuVKxda#CqFmg;#kc?$;=-Jrv+)a^BFo#dHEEbqLg^D3q?yZ}c<0 zqN9|b@)3H9t!f;9uWVjdO%}>Q?I=5Crv0>!notD&KkLZxzbd4^Sx1ilwve*9l~Ps@ z#q>97$??A|roT~3E&rQhs=$9$PQLUO3Em)Qbgp8~`24w?32RF^uXyEEzc=R`$;H=& zWO7c}a4mVw#*>wjk6j#^E4kI3qPdf2KJ{g1*fWFWypuOaa@ezVnUV{?$j-?V)BdQs z`)Vm(n%fx~UZZ~3Yg^F#+7h^<|3r<+A{8;rbHHA}YK&7tr>+ML6M8 zFM>G8MS!hERGVOvP!5DQgiuIL3g!wfRzzoET{Bq?z{;#%H084DRWMh#vV66k`XFS{ z1ZPTtoa)g_&ZFi9b3qqV9MDWZFtZ9X)bm(271zu%CO+!>d~siP^`e=@6YXl75H65Q zVpkJ{9F*CaP^g&m-bcCAybvyHRZ&Epe@(3cYEDfptMWE?r%CX%L1C zkZDvEFmkKtP{axaSjDAI$GAzD8NCW%y(z55E`rZ4_SHH%U@Q-Gd><34yjxgInZFi7 zBU_jvnuC^CO=!VAT_S8oc&U6XxoP@Xh9bx(ghI|Oi*wjL&R7lkHB*&rWpP-tpv{#m z6rjuta+Olvt&n4%KrZ0Yno(9kHLNu^bP=Qoa!anH2nwN%JIfR->p_sH(>zgESa^|@ zN~#&H-4*Hru+@4Ib@y#cg=EY_QPnNXl820hV(NSbg3K0ekIa_hV$X%eg~aak0@L$l zX&aMQ7rYX}d;X%5iVt_63|=?Pa8?JeB(lG9V;P~9aYagJe_Oa&h=HJ$0`1VoTIyA} zMQhYXQ&1ByN^3?%XCq9&IT03?%Ql@tvCSLQGMg%UFimqewKdDG9=JX#t{sQDEYpM+ zolQa=5XuO_XF;JHs&spc3$|pJm0&E-Th{KSP+U!+ocdRL%fy!$=`o2>c{Q#BhuCef z1-k-eA*WByN@`nYcgN>+HEpd0K^4`z9l51TkS?GS=S@Oo5Gtux9XY^7fVYMf(%>qq zSDm=9n$yYB`7?&&En&5`Nzk<;5`4wX8!zATV5TjkRaCAn78$xqM|3gG^nswNYF-zv z=ThP|!8Efw#;U1TT{zw~rY)2pXe%TL)pas{EU!|#+VfRJ{IYm`M56-VkvmFSv zAnd~C5D&sKa%+PdQ17p}iAPMm?IE^~YSNPjx%6to{9c%Zz97_9cYE@9E5Yb^(HO(V z-kG+gql)V1?x5GVX5f2(R$u+lo4uX)8r4)Q;@p|gSVYZuYUXet=>9^VWYt(yMNQ`X zI#0boXdv-V{W;u&v=yt&4%rsGhQj+JEJ$MJY9WaqA+k53%*ehAS|fO|tV6s?NN~4p zezcj*QJ^&jEu!V1jLvF_v3*R5V?k{KYTKltLUrj?+R?gwO-F}<7NFYoCHg4N*umefj0bO7W1nx_oA^l6!*FGOS>`n8#d63w`1H&?j^Sr%;_oZCyx;JgEAp=#wIp87ffh_TUc z92jb$A_sHg>mehs1%{aS&H)kGTTPBhH`TDm=1Z6mA`=H&b`BC{ohg||ZPXv{@K~3BhC2~2^H-magJB*Jj^HYQzuybY;W+Yd5DM9 zuI5R7b`V}BwjgWL@ql2_`uLf6yg z(Um~0b?O+i!;S!{XSxV}W6e;$jj^6kqGI3RCLSi0o-?+F(o4M>o8C}#Us^HF zjKu^<>y221?~7Gc##=T6TFlV#=In?8EmG5}I8%c2IfryB=awEUsXBwQq((^$YE})) zNYS+|lxX$+1k0+c%QI!68OJ^#^br|(Yj#x6CtBht1?6gZePK`@KevXbCE4n@p9Cu~ zD{G?LbC%>!7CvpdEPVY%ZCtAmd-`;Csyj^HFz^P5(0f_AZ^oj~0Zs#18=3&}Kp5Kg zzzA7N(i^|4bTmy$XAo#92Xv!Mr)hs=ozpZ~=LUneqH;t=#VYE$8J#H5hJe=YUZCptXnPS=k!OaJBCPOTUl}qN|!m zNE9aKVz+XBT{_xgDV>oj-weybig81R?DNVS9ybiZC zK~0b*I9|P)&C^`@&?;=J*#vcPj{9o-@6U6Bn8mcEQk8Sa{%g>%XcAX@}YdX@~Etn+q*_ z0d0eAxtONrEV3*Ynouv%lrS0+K2Yrvd3L%NADfm8$JlgjQz2i(UZk=qKF_^MR(=nG#+APFe{a%2FsUAx$t4-=_PCPiXB`-s3^|6~X-)it2 zC_7WDzw-UW(ot=@jkzM^P<`Ew?D^LgOaA9UNYZIfy}?!8+HTo*&KGgLheX=VcFiL# zQ|8f!khyu+Tc0S>AWfm%fkVR z)?62?h0wgBWMw-|J7U|sE&{FQ*txlUMgL;|5tiS;i= z*R=ECrBM>{{Jt2HzCY{hp+o6l*p4JVl4t$NIFcB%%A!^t-1Hof2e*&au+=#3byVf@ z_R@ftMU|}inkw77PlRfjvTIE-jWM=FmHCw0yC#A*#dhkkRMl9+Wz@M(xl%f7gDD{x z5|#;}t7}Xji^x%cRxd{Z%hjPZmh(lIx0)cyTA`Y(wVVP0cGE}?L% z3){)XDiyxYvWIe+p;IJgtdNtf+t zXro%b$#OI#ty#|)Y0aCUKq4gq@?EcPi3|NTKc07>^sSFuS--`?pk$+C11v|OuhaN|qWwu_WToJZb8 zNFzQ3>jDQlqb3H3!1Q8w)r!_DwQ?A;Zj`E}uJ5&YVVmejz{p+7Pqeu`o7vXDqoBo2 zsA$ihuJbDUP1{>R- z9>*=Y(xI94#MBiA-g)IX%za$$WYCeSN*uB1fB+*Da&B=!eR0HcuWkNal#&mui20Xg zhs6MNM&o`z+WZAr|qQA5(>$Yk66_RxCMyRTL%p%#gO~0Z(JeIyq zmlw!*pNkiuIy^NY{;HT4U5U%th#?L__>bX~Yv#u-^bcT%^a)-zak8@hmMLGX3W zub>i6SZ0#Vwj1i^35#vE$K;#Jandp-RjwsVmEVHogj8Y({Xx48TKLGW zs?cdmaBPQ-chs=cmcvHZbkX%E)8($pcZQ=}HDQ~%_aOd2?uzym%C?B#S2fPMFXFZh z*#lMM9Nwj$Kg$(eI&2${uZ7^YA(Qu1Iu!Dr>LH8>j47cCHnRlT)%vs_L7;u3ww<>u zZLW5!3DRyKslZfj>oP)$Q&)%-=VO^b`xEif?xIDBE8&_a34bEI`HRZid9I4nHcQ2Q z3!DGEqiJqMBx*HH)IJ5R%-wPsq@^>y1LM^qH-_X$n|8Bn%cn)2q7U>wc87&p1jh5r<7ofG9UD~ymcjMX?%QVe(d-P0s-4=Wy z?FY5;3YW;Zqs(akOJSzlZ|megLQh(r;EXL)$^Pw4SsG;j_7h?i=xjI5jp)*)eUx8- z`~&j%{i+_euo4O#dkMwQ68n7B@hTzX`!d^s-ajF4$^8!M$#qM4*|yfdfZ-iiM)r*9 zi?S{(+iyAk1zMg5Wj$;yUpI5@gPdvo3Tll9&FwLgIQrUv=2Vil`3HEMvO6$Zv|Y!}1fbqHx$b zPnD3LL8PBo>0*#wueMW8G>gH`U(0lopK;j_Ic#U7#liahNo$q%+&$DeUO&23FUX9G7T<9G8?+nV+xL&{TD@7^ M@cz~N#l+D60T5}ipa1{> diff --git a/RenX.Core/RenX.Core.vcxproj b/RenX.Core/RenX.Core.vcxproj index 18d2c1f..d0ebcb1 100644 --- a/RenX.Core/RenX.Core.vcxproj +++ b/RenX.Core/RenX.Core.vcxproj @@ -71,6 +71,7 @@ + diff --git a/RenX.Core/RenX.Core.vcxproj.filters b/RenX.Core/RenX.Core.vcxproj.filters index 1027a38..09f1e2b 100644 --- a/RenX.Core/RenX.Core.vcxproj.filters +++ b/RenX.Core/RenX.Core.vcxproj.filters @@ -50,6 +50,9 @@ Header Files + + Header Files + diff --git a/RenX.Core/RenX_BuildingInfo.h b/RenX.Core/RenX_BuildingInfo.h new file mode 100644 index 0000000..dc0433a --- /dev/null +++ b/RenX.Core/RenX_BuildingInfo.h @@ -0,0 +1,59 @@ +/** + * Copyright (C) 2015 Justin James. + * + * This license must be preserved. + * Any applications, libraries, or code which make any use of any + * component of this program must not be commercial, unless explicit + * permission is granted from the original author. The use of this + * program for non-profit purposes is permitted. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * In the event that this license restricts you from making desired use of this program, contact the original author. + * Written by Justin James + */ + +#if !defined _RENX_BUILDINGINFO_H_HEADER +#define _RENX_BUILDINGINFO_H_HEADER + +/** + * @file RenX_BuildingInfo.h + * @brief Defines the BuildingInfo structure. + */ + +#include "Jupiter/String.h" +#include "Jupiter/INIFile.h" +#include "RenX.h" + +/** DLL Linkage Nagging */ +#if defined _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4251) +#endif + +namespace RenX +{ + + /** + * @brief Includes all of the tracked information about a building. + */ + struct RENX_API BuildingInfo + { + Jupiter::StringS name; + TeamType team = TeamType::Other; + int health = 0; + int max_health = 0; + bool capturable = false; + mutable Jupiter::INIFile varData; + }; + +} + +/** Re-enable warnings */ +#if defined _MSC_VER +#pragma warning(pop) +#endif + +#endif // _RENX_BUILDINGINFO_H_HEADER \ No newline at end of file diff --git a/RenX.Core/RenX_Core.cpp b/RenX.Core/RenX_Core.cpp index 7f5fe12..9de547d 100644 --- a/RenX.Core/RenX_Core.cpp +++ b/RenX.Core/RenX_Core.cpp @@ -1,5 +1,5 @@ /** - * Copyright (C) 2014 Justin James. + * Copyright (C) 2014-2015 Justin James. * * This license must be preserved. * Any applications, libraries, or code which make any use of any @@ -34,7 +34,7 @@ RenX::Core *RenX::getCore() return &pluginInstance; } -RenX::Core::Core() +void RenX::Core::init() { const Jupiter::ReadableString &serverList = Jupiter::IRC::Client::Config->get(STRING_LITERAL_AS_REFERENCE("RenX"), STRING_LITERAL_AS_REFERENCE("Servers")); RenX::Core::translationsFile.readFile(Jupiter::IRC::Client::Config->get(STRING_LITERAL_AS_REFERENCE("RenX"), STRING_LITERAL_AS_REFERENCE("TranslationsFile"), STRING_LITERAL_AS_REFERENCE("Translations.ini"))); @@ -149,11 +149,11 @@ int RenX::Core::addCommand(RenX::GameCommand *command) int RenX::Core::think() { - size_t a = 0; - while (a < RenX::Core::servers.size()) - if (RenX::Core::servers.get(a)->think() != 0) - delete RenX::Core::servers.remove(a); - else a++; + size_t index = 0; + while (index < RenX::Core::servers.size()) + if (RenX::Core::servers.get(index)->think() != 0) + delete RenX::Core::servers.remove(index); + else ++index; return Jupiter::Plugin::think(); } @@ -165,6 +165,14 @@ extern "C" __declspec(dllexport) Jupiter::Plugin *getPlugin() return &pluginInstance; } +// Load + +extern "C" __declspec(dllexport) bool load(void) +{ + pluginInstance.init(); + return true; +} + // Unload extern "C" __declspec(dllexport) void unload(void) diff --git a/RenX.Core/RenX_Core.h b/RenX.Core/RenX_Core.h index d5c504e..21be70d 100644 --- a/RenX.Core/RenX_Core.h +++ b/RenX.Core/RenX_Core.h @@ -1,5 +1,5 @@ /** - * Copyright (C) 2014 Justin James. + * Copyright (C) 2014-2015 Justin James. * * This license must be preserved. * Any applications, libraries, or code which make any use of any @@ -157,9 +157,9 @@ namespace RenX int addCommand(GameCommand *command); /** - * @brief Default constructor for the Core class. + * @brief Initializes the Core. */ - Core(); + void init(); /** * Destructor for the Core class. diff --git a/RenX.Core/RenX_Functions.cpp b/RenX.Core/RenX_Functions.cpp index 720e548..3ec861f 100644 --- a/RenX.Core/RenX_Functions.cpp +++ b/RenX.Core/RenX_Functions.cpp @@ -445,7 +445,7 @@ const Jupiter::ReferenceString RenX::translateName(const Jupiter::ReadableString return Jupiter::ReferenceString::empty; Jupiter::ReferenceString iniTranslation = RenX::getCore()->getTranslationsFile().get(STRING_LITERAL_AS_REFERENCE("Name"), obj); - if (iniTranslation.isEmpty() == false) + if (iniTranslation.isNotEmpty()) return iniTranslation; static Jupiter::ReferenceString object; @@ -778,7 +778,7 @@ Jupiter::String RenX::getFormattedPlayerName(const RenX::PlayerInfo *player) void RenX::sanitizeString(Jupiter::StringType &str) { - if (str.isEmpty() == false) + if (str.isNotEmpty()) { str.replace('|', '/'); if (str.get(str.size() - 1) == '\\') diff --git a/RenX.Core/RenX_Server.cpp b/RenX.Core/RenX_Server.cpp index 68cfa46..d35c758 100644 --- a/RenX.Core/RenX_Server.cpp +++ b/RenX.Core/RenX_Server.cpp @@ -22,6 +22,7 @@ #include "IRC_Bot.h" #include "RenX_Server.h" #include "RenX_PlayerInfo.h" +#include "RenX_BuildingInfo.h" #include "RenX_GameCommand.h" #include "RenX_Functions.h" #include "RenX_Plugin.h" @@ -82,8 +83,14 @@ int RenX::Server::think() } return 0; } - if (RenX::Server::rconVersion >= 3 && std::chrono::steady_clock::now() > RenX::Server::lastClientListUpdate + RenX::Server::clientUpdateRate) - RenX::Server::updateClientList(); + if (RenX::Server::rconVersion >= 3) + { + if (RenX::Server::clientUpdateRate != std::chrono::milliseconds::zero() && std::chrono::steady_clock::now() > RenX::Server::lastClientListUpdate + RenX::Server::clientUpdateRate) + RenX::Server::updateClientList(); + + if (RenX::Server::buildingUpdateRate != std::chrono::milliseconds::zero() && std::chrono::steady_clock::now() > RenX::Server::lastBuildingListUpdate + RenX::Server::buildingUpdateRate) + RenX::Server::updateBuildingList(); + } } return 0; } @@ -198,6 +205,14 @@ int RenX::Server::sendData(const Jupiter::ReadableString &data) return RenX::Server::sock.send(data); } +RenX::BuildingInfo *RenX::Server::getBuildingByName(const Jupiter::ReadableString &name) const +{ + for (size_t index = 0; index != RenX::Server::buildings.size(); ++index) + if (RenX::Server::buildings.get(index)->name.equalsi(name)) + return RenX::Server::buildings.get(index); + return nullptr; +} + RenX::PlayerInfo *RenX::Server::getPlayer(int id) const { if (RenX::Server::players.size() == 0) return nullptr; @@ -373,14 +388,20 @@ bool RenX::Server::updateClientList() if (RenX::Server::players.get(i)->isBot) botCount++; - bool r; + int r = 0; if (RenX::Server::players.size() != botCount) r = RenX::Server::sock.send(STRING_LITERAL_AS_REFERENCE("cclientvarlist ID\xA0""SCORE\xA0""CREDITS\xA0""PING\n")) > 0; if (botCount != 0) r |= RenX::Server::sock.send(STRING_LITERAL_AS_REFERENCE("cbotvarlist ID\xA0""SCORE\xA0""CREDITS\n")) > 0; - return r; + return r != 0; +} + +bool RenX::Server::updateBuildingList() +{ + RenX::Server::lastBuildingListUpdate = std::chrono::steady_clock::now(); + return RenX::Server::sock.send(STRING_LITERAL_AS_REFERENCE("cbinfo\n")) > 0; } bool RenX::Server::gameover() @@ -498,7 +519,7 @@ bool RenX::Server::changeTeam(RenX::PlayerInfo *player, bool resetCredits) const Jupiter::ReadableString &RenX::Server::getPrefix() const { - static Jupiter::StringS parsed; + static Jupiter::String parsed; RenX::processTags(parsed = RenX::Server::IRCPrefix, this); return parsed; } @@ -627,7 +648,7 @@ void RenX::Server::addCommand(RenX::GameCommand *command) if (RenX::Server::commandAccessLevels != nullptr) { const Jupiter::ReadableString &accessLevel = RenX::Server::commandAccessLevels->get(command->getTrigger()); - if (accessLevel.isEmpty() == false) + if (accessLevel.isNotEmpty()) command->setAccessLevel(accessLevel.asInt()); } if (RenX::Server::commandAliases != nullptr) @@ -703,7 +724,7 @@ void RenX::Server::sendPubChan(const char *fmt, ...) const va_start(args, fmt); Jupiter::StringL msg; const Jupiter::ReadableString &serverPrefix = RenX::Server::getPrefix(); - if (serverPrefix.isEmpty() == false) + if (serverPrefix.isNotEmpty()) { msg += serverPrefix; msg += ' '; @@ -718,7 +739,7 @@ void RenX::Server::sendPubChan(const char *fmt, ...) const void RenX::Server::sendPubChan(const Jupiter::ReadableString &msg) const { const Jupiter::ReadableString &prefix = this->getPrefix(); - if (prefix.isEmpty() == false) + if (prefix.isNotEmpty()) { Jupiter::String m(msg.size() + prefix.size() + 1); m.set(prefix); @@ -738,7 +759,7 @@ void RenX::Server::sendAdmChan(const char *fmt, ...) const va_start(args, fmt); Jupiter::StringL msg; const Jupiter::ReadableString &serverPrefix = RenX::Server::getPrefix(); - if (serverPrefix.isEmpty() == false) + if (serverPrefix.isNotEmpty()) { msg += serverPrefix; msg += ' '; @@ -753,7 +774,7 @@ void RenX::Server::sendAdmChan(const char *fmt, ...) const void RenX::Server::sendAdmChan(const Jupiter::ReadableString &msg) const { const Jupiter::ReadableString &prefix = this->getPrefix(); - if (prefix.isEmpty() == false) + if (prefix.isNotEmpty()) { Jupiter::String m(msg.size() + prefix.size() + 1); m.set(prefix); @@ -774,7 +795,7 @@ void RenX::Server::sendLogChan(const char *fmt, ...) const va_start(args, fmt); Jupiter::StringL msg; const Jupiter::ReadableString &serverPrefix = RenX::Server::getPrefix(); - if (serverPrefix.isEmpty() == false) + if (serverPrefix.isNotEmpty()) { msg += serverPrefix; msg += ' '; @@ -794,7 +815,7 @@ void RenX::Server::sendLogChan(const Jupiter::ReadableString &msg) const { IRC_Bot *server; const Jupiter::ReadableString &prefix = this->getPrefix(); - if (prefix.isEmpty() == false) + if (prefix.isNotEmpty()) { Jupiter::String m(msg.size() + prefix.size() + 1); m.set(prefix); @@ -937,7 +958,7 @@ void RenX::Server::processLine(const Jupiter::ReadableString &line) banDatabase->deactivate(i); else if ((this->localSteamBan && entry->steamid != 0 && entry->steamid == player->steamid) || (this->localIPBan && entry->ip != 0 && entry->ip == player->ip32) - || (this->localNameBan && entry->name.isEmpty() == false && entry->name.equalsi(player->name))) + || (this->localNameBan && entry->name.isNotEmpty() && entry->name.equalsi(player->name))) { char timeStr[256]; if (entry->length == 0) @@ -983,7 +1004,7 @@ void RenX::Server::processLine(const Jupiter::ReadableString &line) { bool recalcUUID = false; r->team = team; - if (r->ip32 == 0 && ip.isEmpty() == false) + if (r->ip32 == 0 && ip.isNotEmpty()) { r->ip = ip; r->ip32 = Jupiter::Socket::pton4(Jupiter::CStringS(r->ip).c_str()); @@ -994,7 +1015,7 @@ void RenX::Server::processLine(const Jupiter::ReadableString &line) r->steamid = steamid; recalcUUID = true; } - if (r->name.size() == 0) + if (r->name.isEmpty()) { r->name = name; recalcUUID = true; @@ -1013,7 +1034,7 @@ void RenX::Server::processLine(const Jupiter::ReadableString &line) return getPlayerOrAdd(name, id, team, isBot, 0U, Jupiter::ReferenceString::empty); }; - if (buff.size() != 0) + if (buff.isNotEmpty()) { switch (header[0]) { @@ -1022,7 +1043,7 @@ void RenX::Server::processLine(const Jupiter::ReadableString &line) { // ID | IP | Steam ID | Admin Status | Team | Name header.shiftRight(1); - if (header.isEmpty() == false) + if (header.isNotEmpty()) { bool isBot = false; int id; @@ -1304,16 +1325,69 @@ void RenX::Server::processLine(const Jupiter::ReadableString &line) } buff.shiftLeft(1); } + else if (this->lastCommand.equalsi("binfo") || this->lastCommand.equalsi("buildinginfo") || this->lastCommand.equalsi("blist") || this->lastCommand.equalsi("buildinglist")) + { + buff.shiftRight(1); + if (this->commandListFormat.isEmpty()) + this->commandListFormat = buff; + else + { + /* + lRCON Command; DevBot executed: binfo + rBuilding Health MaxHealth Team Capturable + rRx_Building_Refinery_GDI 4000 4000 GDI False + */ + Jupiter::INIFile::Section table; + size_t i = this->commandListFormat.tokenCount(RenX::DelimC); + while (i-- != 0) + table.set(this->commandListFormat.getToken(i, RenX::DelimC), buff.getToken(i, RenX::DelimC)); + + Jupiter::INIFile::Section::KeyValuePair *pair; + RenX::BuildingInfo *building; + + pair = table.getPair(STRING_LITERAL_AS_REFERENCE("Building")); + if (pair != nullptr) + { + building = this->getBuildingByName(pair->getValue()); + if (building == nullptr) + { + building = new RenX::BuildingInfo(); + RenX::Server::buildings.add(building); + building->name = pair->getValue(); + } + + pair = table.getPair(STRING_LITERAL_AS_REFERENCE("Health")); + if (pair != nullptr) + building->health = pair->getValue().asInt(10); + + pair = table.getPair(STRING_LITERAL_AS_REFERENCE("MaxHealth")); + if (pair != nullptr) + building->max_health = pair->getValue().asInt(10); + + pair = table.getPair(STRING_LITERAL_AS_REFERENCE("Team")); + if (pair != nullptr) + building->team = RenX::getTeam(pair->getValue()); + + pair = table.getPair(STRING_LITERAL_AS_REFERENCE("Capturable")); + if (pair != nullptr) + building->capturable = pair->getValue().asBool(); + } + } + buff.shiftLeft(1); + } else if (this->lastCommand.equalsi("map")) this->map = buff.substring(1); else if (this->lastCommand.equalsi("serverinfo")) { - // "Port" | Port | "Name" | Name | "Passworded" | "True"/"False" | "Level" | Level - buff.shiftRight(1); - this->port = static_cast(buff.getToken(1, RenX::DelimC).asUnsignedInt(10)); - this->serverName = buff.getToken(3, RenX::DelimC); - this->map = buff.getToken(7, RenX::DelimC); - buff.shiftLeft(1); + if (this->lastCommandParams.isEmpty()) + { + // "Port" | Port | "Name" | Name | "Passworded" | "True"/"False" | "Level" | Level + buff.shiftRight(1); + this->port = static_cast(buff.getToken(1, RenX::DelimC).asUnsignedInt(10)); + this->serverName = buff.getToken(3, RenX::DelimC); + this->map = buff.getToken(7, RenX::DelimC); + buff.shiftLeft(1); + } } else if (this->lastCommand.equalsi("changename")) { @@ -1593,7 +1667,7 @@ void RenX::Server::processLine(const Jupiter::ReadableString &line) // "player" | Player | "suicide by" | Damage Type // NOTE: Filter these out when Player.isEmpty(). Jupiter::ReferenceString playerToken = buff.getToken(3, RenX::DelimC); - if (playerToken.isEmpty() == false) + if (playerToken.isNotEmpty()) { RenX::PlayerInfo *player = parseGetPlayerOrAdd(playerToken); Jupiter::ReferenceString type = buff.getToken(4, RenX::DelimC); @@ -1937,7 +2011,10 @@ void RenX::Server::processLine(const Jupiter::ReadableString &line) for (size_t i = 0; i < xPlugins.size(); i++) xPlugins.get(i)->RenX_OnExecute(this, user, command); if (this->rconUser.equals(user)) + { this->lastCommand = cmd; + this->lastCommandParams = command.gotoWord(1, " "); + } } } else if (subHeader.equals("Subscribed;")) @@ -2269,6 +2346,7 @@ void RenX::Server::processLine(const Jupiter::ReadableString &line) xPlugins.get(i)->RenX_OnCommand(this, buff); this->commandListFormat.set(Jupiter::ReferenceString::empty); this->lastCommand = Jupiter::ReferenceString::empty; + this->lastCommandParams = Jupiter::ReferenceString::empty; buff.shiftLeft(1); break; @@ -2289,6 +2367,7 @@ void RenX::Server::processLine(const Jupiter::ReadableString &line) RenX::Server::sock.send(STRING_LITERAL_AS_REFERENCE("s\n")); RenX::Server::send(STRING_LITERAL_AS_REFERENCE("serverinfo")); RenX::Server::fetchClientList(); + RenX::Server::updateBuildingList(); this->firstGame = true; this->seamless = true; @@ -2423,6 +2502,7 @@ void RenX::Server::init() RenX::Server::steamFormat = Jupiter::IRC::Client::Config->getInt(RenX::Server::configSection, STRING_LITERAL_AS_REFERENCE("SteamFormat"), 16); RenX::Server::neverSay = Jupiter::IRC::Client::Config->getBool(RenX::Server::configSection, STRING_LITERAL_AS_REFERENCE("NeverSay"), false); RenX::Server::clientUpdateRate = std::chrono::milliseconds(Jupiter::IRC::Client::Config->getInt(RenX::Server::configSection, STRING_LITERAL_AS_REFERENCE("ClientUpdateRate"), 2500)); + RenX::Server::buildingUpdateRate = std::chrono::milliseconds(Jupiter::IRC::Client::Config->getInt(RenX::Server::configSection, STRING_LITERAL_AS_REFERENCE("BuildingUpdateRate"), 7500)); Jupiter::INIFile &commandsFile = RenX::getCore()->getCommandsFile(); RenX::Server::commandAccessLevels = commandsFile.getSection(RenX::Server::configSection); diff --git a/RenX.Core/RenX_Server.h b/RenX.Core/RenX_Server.h index 812d3ec..71abd4c 100644 --- a/RenX.Core/RenX_Server.h +++ b/RenX.Core/RenX_Server.h @@ -45,6 +45,7 @@ namespace RenX { /** Forward declarations */ struct PlayerInfo; + struct BuildingInfo; class GameCommand; class Core; @@ -82,6 +83,7 @@ namespace RenX public: // RenX::Server Jupiter::DLList players; /** A list of players in the server */ + Jupiter::ArrayList buildings; /** A list of buildings in the server */ Jupiter::INIFile varData; /** This may be replaced later with a more dedicated type. */ /** @@ -190,6 +192,14 @@ namespace RenX */ int sendData(const Jupiter::ReadableString &data); + /** + * @brief Fetches a player's data, based on their name. + * + * @param name Name of the player. + * @return A player's data on success, nullptr otherwise. + */ + RenX::BuildingInfo *getBuildingByName(const Jupiter::ReadableString &name) const; + /** * @brief Fetches a player's data based on their ID number. * @@ -314,6 +324,13 @@ namespace RenX */ bool updateClientList(); + /** + * @brief Sends a building list request. + * + * @return True on success, false otherwise. + */ + bool updateBuildingList(); + /** * @brief Forces the current game to end. * @@ -800,6 +817,7 @@ namespace RenX time_t lastAttempt = 0; int attempts = 0; std::chrono::steady_clock::time_point lastClientListUpdate = std::chrono::steady_clock::now(); + std::chrono::steady_clock::time_point lastBuildingListUpdate = std::chrono::steady_clock::now(); Jupiter::String lastLine; Jupiter::StringS commandListFormat; Jupiter::StringS gameVersion; @@ -812,6 +830,7 @@ namespace RenX time_t delay; int maxAttempts; std::chrono::milliseconds clientUpdateRate; + std::chrono::milliseconds buildingUpdateRate; int steamFormat; /** 16 = hex, 10 = base 10, 8 = octal, -2 = SteamID 2, -3 = SteamID 3 */ bool rconBan; bool localBan; @@ -831,6 +850,7 @@ namespace RenX Jupiter::StringS rconUser; Jupiter::StringS serverName; Jupiter::StringS lastCommand; + Jupiter::StringS lastCommandParams; Jupiter::StringS map; Jupiter::INIFile::Section *commandAccessLevels; Jupiter::INIFile::Section *commandAliases; diff --git a/RenX.Core/RenX_Tags.cpp b/RenX.Core/RenX_Tags.cpp index 82ed6c3..10f3553 100644 --- a/RenX.Core/RenX_Tags.cpp +++ b/RenX.Core/RenX_Tags.cpp @@ -253,101 +253,109 @@ TagsImp::TagsImp() this->loseScoreTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("LoseScoreTag"), STRING_LITERAL_AS_REFERENCE("{LOSESCORE}")); } +#define PROCESS_TAG(tag, value) \ +while(true) { \ +index = msg.find(tag); \ +if (index == Jupiter::INVALID_INDEX) break; \ +msg.replace(index, tag.size(), value); } + + void TagsImp::processTags(Jupiter::StringType &msg, const RenX::Server *server, const RenX::PlayerInfo *player, const RenX::PlayerInfo *victim) { - msg.replace(this->INTERNAL_DATE_TAG, Jupiter::ReferenceString(getTimeFormat(this->dateFmt.c_str()))); - msg.replace(this->INTERNAL_TIME_TAG, Jupiter::ReferenceString(getTimeFormat(this->timeFmt.c_str()))); + size_t index; + PROCESS_TAG(this->INTERNAL_DATE_TAG, Jupiter::ReferenceString(getTimeFormat(this->dateFmt.c_str()))); + PROCESS_TAG(this->INTERNAL_TIME_TAG, Jupiter::ReferenceString(getTimeFormat(this->timeFmt.c_str()))); if (server != nullptr) { - msg.replace(this->INTERNAL_RCON_VERSION_TAG, Jupiter::StringS::Format("%u", server->getVersion())); - msg.replace(this->INTERNAL_GAME_VERSION_TAG, server->getGameVersion()); - msg.replace(this->INTERNAL_RULES_TAG, server->getRules()); - msg.replace(this->INTERNAL_USER_TAG, server->getUser()); - msg.replace(this->INTERNAL_SERVER_NAME_TAG, server->getName()); - msg.replace(this->INTERNAL_MAP_TAG, server->getMap()); - msg.replace(this->INTERNAL_SERVER_HOSTNAME_TAG, server->getHostname()); - msg.replace(this->INTERNAL_SERVER_PORT_TAG, Jupiter::StringS::Format("%u", server->getPort())); - msg.replace(this->INTERNAL_SOCKET_HOSTNAME_TAG, server->getSocketHostname()); - msg.replace(this->INTERNAL_SOCKET_PORT_TAG, Jupiter::StringS::Format("%u", server->getSocketPort())); - msg.replace(this->INTERNAL_SERVER_PREFIX_TAG, server->getPrefix()); + PROCESS_TAG(this->INTERNAL_RCON_VERSION_TAG, Jupiter::StringS::Format("%u", server->getVersion())); + PROCESS_TAG(this->INTERNAL_GAME_VERSION_TAG, server->getGameVersion()); + PROCESS_TAG(this->INTERNAL_RULES_TAG, server->getRules()); + PROCESS_TAG(this->INTERNAL_USER_TAG, server->getUser()); + PROCESS_TAG(this->INTERNAL_SERVER_NAME_TAG, server->getName()); + PROCESS_TAG(this->INTERNAL_MAP_TAG, server->getMap()); + PROCESS_TAG(this->INTERNAL_SERVER_HOSTNAME_TAG, server->getHostname()); + PROCESS_TAG(this->INTERNAL_SERVER_PORT_TAG, Jupiter::StringS::Format("%u", server->getPort())); + PROCESS_TAG(this->INTERNAL_SOCKET_HOSTNAME_TAG, server->getSocketHostname()); + PROCESS_TAG(this->INTERNAL_SOCKET_PORT_TAG, Jupiter::StringS::Format("%u", server->getSocketPort())); + PROCESS_TAG(this->INTERNAL_SERVER_PREFIX_TAG, server->getPrefix()); if (player != nullptr) { - msg.replace(this->INTERNAL_STEAM_TAG, server->formatSteamID(player)); + PROCESS_TAG(this->INTERNAL_STEAM_TAG, server->formatSteamID(player)); } if (victim != nullptr) { - msg.replace(this->INTERNAL_VICTIM_STEAM_TAG, server->formatSteamID(victim)); + PROCESS_TAG(this->INTERNAL_VICTIM_STEAM_TAG, server->formatSteamID(victim)); } } if (player != nullptr) { - msg.replace(this->INTERNAL_NAME_TAG, RenX::getFormattedPlayerName(player)); - msg.replace(this->INTERNAL_RAW_NAME_TAG, player->name); - msg.replace(this->INTERNAL_IP_TAG, player->ip); - msg.replace(this->INTERNAL_UUID_TAG, player->uuid); - msg.replace(this->INTERNAL_ID_TAG, Jupiter::StringS::Format("%d", player->id)); - msg.replace(this->INTERNAL_CHARACTER_TAG, RenX::translateName(player->character)); - msg.replace(this->INTERNAL_VEHICLE_TAG, RenX::translateName(player->vehicle)); - msg.replace(this->INTERNAL_ADMIN_TAG, player->adminType); - msg.replace(this->INTERNAL_PREFIX_TAG, player->formatNamePrefix); - msg.replace(this->INTERNAL_GAME_PREFIX_TAG, player->gamePrefix); - msg.replace(this->INTERNAL_TEAM_COLOR_TAG, RenX::getTeamColor(player->team)); - msg.replace(this->INTERNAL_TEAM_SHORT_TAG, RenX::getTeamName(player->team)); - msg.replace(this->INTERNAL_TEAM_LONG_TAG, RenX::getFullTeamName(player->team)); - msg.replace(this->INTERNAL_PING_TAG, Jupiter::StringS::Format("%hu", player->ping)); - msg.replace(this->INTERNAL_SCORE_TAG, Jupiter::StringS::Format("%.0f", player->score)); - msg.replace(this->INTERNAL_CREDITS_TAG, Jupiter::StringS::Format("%.0f", player->credits)); - msg.replace(this->INTERNAL_KILLS_TAG, Jupiter::StringS::Format("%u", player->kills)); - msg.replace(this->INTERNAL_DEATHS_TAG, Jupiter::StringS::Format("%u", player->deaths)); - msg.replace(this->INTERNAL_KDR_TAG, Jupiter::StringS::Format("%.2f", static_cast(player->kills) / (player->deaths == 0 ? 1.0f : static_cast(player->deaths)))); - msg.replace(this->INTERNAL_SUICIDES_TAG, Jupiter::StringS::Format("%u", player->suicides)); - msg.replace(this->INTERNAL_HEADSHOTS_TAG, Jupiter::StringS::Format("%u", player->headshots)); - msg.replace(this->INTERNAL_VEHICLE_KILLS_TAG, Jupiter::StringS::Format("%u", player->vehicleKills)); - msg.replace(this->INTERNAL_BUILDING_KILLS_TAG, Jupiter::StringS::Format("%u", player->buildingKills)); - msg.replace(this->INTERNAL_DEFENCE_KILLS_TAG, Jupiter::StringS::Format("%u", player->defenceKills)); - msg.replace(this->INTERNAL_WINS_TAG, Jupiter::StringS::Format("%u", player->wins)); - msg.replace(this->INTERNAL_LOSES_TAG, Jupiter::StringS::Format("%u", player->loses)); - msg.replace(this->INTERNAL_BEACON_PLACEMENTS_TAG, Jupiter::StringS::Format("%u", player->beaconPlacements)); - msg.replace(this->INTERNAL_BEACON_DISARMS_TAG, Jupiter::StringS::Format("%u", player->beaconDisarms)); - msg.replace(this->INTERNAL_CAPTURES_TAG, Jupiter::StringS::Format("%u", player->captures)); - msg.replace(this->INTERNAL_STEALS_TAG, Jupiter::StringS::Format("%u", player->steals)); - msg.replace(this->INTERNAL_STOLEN_TAG, Jupiter::StringS::Format("%u", player->stolen)); - msg.replace(this->INTERNAL_ACCESS_TAG, Jupiter::StringS::Format("%d", player->access)); + PROCESS_TAG(this->INTERNAL_NAME_TAG, RenX::getFormattedPlayerName(player)); + PROCESS_TAG(this->INTERNAL_RAW_NAME_TAG, player->name); + PROCESS_TAG(this->INTERNAL_IP_TAG, player->ip); + PROCESS_TAG(this->INTERNAL_UUID_TAG, player->uuid); + PROCESS_TAG(this->INTERNAL_ID_TAG, Jupiter::StringS::Format("%d", player->id)); + PROCESS_TAG(this->INTERNAL_CHARACTER_TAG, RenX::translateName(player->character)); + PROCESS_TAG(this->INTERNAL_VEHICLE_TAG, RenX::translateName(player->vehicle)); + PROCESS_TAG(this->INTERNAL_ADMIN_TAG, player->adminType); + PROCESS_TAG(this->INTERNAL_PREFIX_TAG, player->formatNamePrefix); + PROCESS_TAG(this->INTERNAL_GAME_PREFIX_TAG, player->gamePrefix); + PROCESS_TAG(this->INTERNAL_TEAM_COLOR_TAG, RenX::getTeamColor(player->team)); + PROCESS_TAG(this->INTERNAL_TEAM_SHORT_TAG, RenX::getTeamName(player->team)); + PROCESS_TAG(this->INTERNAL_TEAM_LONG_TAG, RenX::getFullTeamName(player->team)); + PROCESS_TAG(this->INTERNAL_PING_TAG, Jupiter::StringS::Format("%hu", player->ping)); + PROCESS_TAG(this->INTERNAL_SCORE_TAG, Jupiter::StringS::Format("%.0f", player->score)); + PROCESS_TAG(this->INTERNAL_CREDITS_TAG, Jupiter::StringS::Format("%.0f", player->credits)); + PROCESS_TAG(this->INTERNAL_KILLS_TAG, Jupiter::StringS::Format("%u", player->kills)); + PROCESS_TAG(this->INTERNAL_DEATHS_TAG, Jupiter::StringS::Format("%u", player->deaths)); + PROCESS_TAG(this->INTERNAL_KDR_TAG, Jupiter::StringS::Format("%.2f", static_cast(player->kills) / (player->deaths == 0 ? 1.0f : static_cast(player->deaths)))); + PROCESS_TAG(this->INTERNAL_SUICIDES_TAG, Jupiter::StringS::Format("%u", player->suicides)); + PROCESS_TAG(this->INTERNAL_HEADSHOTS_TAG, Jupiter::StringS::Format("%u", player->headshots)); + PROCESS_TAG(this->INTERNAL_VEHICLE_KILLS_TAG, Jupiter::StringS::Format("%u", player->vehicleKills)); + PROCESS_TAG(this->INTERNAL_BUILDING_KILLS_TAG, Jupiter::StringS::Format("%u", player->buildingKills)); + PROCESS_TAG(this->INTERNAL_DEFENCE_KILLS_TAG, Jupiter::StringS::Format("%u", player->defenceKills)); + PROCESS_TAG(this->INTERNAL_WINS_TAG, Jupiter::StringS::Format("%u", player->wins)); + PROCESS_TAG(this->INTERNAL_LOSES_TAG, Jupiter::StringS::Format("%u", player->loses)); + PROCESS_TAG(this->INTERNAL_BEACON_PLACEMENTS_TAG, Jupiter::StringS::Format("%u", player->beaconPlacements)); + PROCESS_TAG(this->INTERNAL_BEACON_DISARMS_TAG, Jupiter::StringS::Format("%u", player->beaconDisarms)); + PROCESS_TAG(this->INTERNAL_CAPTURES_TAG, Jupiter::StringS::Format("%u", player->captures)); + PROCESS_TAG(this->INTERNAL_STEALS_TAG, Jupiter::StringS::Format("%u", player->steals)); + PROCESS_TAG(this->INTERNAL_STOLEN_TAG, Jupiter::StringS::Format("%u", player->stolen)); + PROCESS_TAG(this->INTERNAL_ACCESS_TAG, Jupiter::StringS::Format("%d", player->access)); } if (victim != nullptr) { - msg.replace(this->INTERNAL_VICTIM_NAME_TAG, RenX::getFormattedPlayerName(victim)); - msg.replace(this->INTERNAL_VICTIM_RAW_NAME_TAG, victim->name); - msg.replace(this->INTERNAL_VICTIM_IP_TAG, victim->ip); - msg.replace(this->INTERNAL_VICTIM_UUID_TAG, victim->uuid); - msg.replace(this->INTERNAL_VICTIM_ID_TAG, Jupiter::StringS::Format("%d", victim->id)); - msg.replace(this->INTERNAL_VICTIM_CHARACTER_TAG, RenX::translateName(victim->character)); - msg.replace(this->INTERNAL_VICTIM_VEHICLE_TAG, RenX::translateName(victim->vehicle)); - msg.replace(this->INTERNAL_VICTIM_ADMIN_TAG, victim->adminType); - msg.replace(this->INTERNAL_VICTIM_PREFIX_TAG, victim->formatNamePrefix); - msg.replace(this->INTERNAL_VICTIM_GAME_PREFIX_TAG, victim->gamePrefix); - msg.replace(this->INTERNAL_VICTIM_TEAM_COLOR_TAG, RenX::getTeamColor(victim->team)); - msg.replace(this->INTERNAL_VICTIM_TEAM_SHORT_TAG, RenX::getTeamName(victim->team)); - msg.replace(this->INTERNAL_VICTIM_TEAM_LONG_TAG, RenX::getFullTeamName(victim->team)); - msg.replace(this->INTERNAL_VICTIM_PING_TAG, Jupiter::StringS::Format("%hu", victim->ping)); - msg.replace(this->INTERNAL_VICTIM_SCORE_TAG, Jupiter::StringS::Format("%.0f", victim->score)); - msg.replace(this->INTERNAL_VICTIM_CREDITS_TAG, Jupiter::StringS::Format("%.0f", victim->credits)); - msg.replace(this->INTERNAL_VICTIM_KILLS_TAG, Jupiter::StringS::Format("%u", victim->kills)); - msg.replace(this->INTERNAL_VICTIM_DEATHS_TAG, Jupiter::StringS::Format("%u", victim->deaths)); - msg.replace(this->INTERNAL_VICTIM_KDR_TAG, Jupiter::StringS::Format("%.2f", static_cast(victim->kills) / (victim->deaths == 0 ? 1.0f : static_cast(victim->deaths)))); - msg.replace(this->INTERNAL_VICTIM_SUICIDES_TAG, Jupiter::StringS::Format("%u", victim->suicides)); - msg.replace(this->INTERNAL_VICTIM_HEADSHOTS_TAG, Jupiter::StringS::Format("%u", victim->headshots)); - msg.replace(this->INTERNAL_VICTIM_VEHICLE_KILLS_TAG, Jupiter::StringS::Format("%u", victim->vehicleKills)); - msg.replace(this->INTERNAL_VICTIM_BUILDING_KILLS_TAG, Jupiter::StringS::Format("%u", victim->buildingKills)); - msg.replace(this->INTERNAL_VICTIM_DEFENCE_KILLS_TAG, Jupiter::StringS::Format("%u", victim->defenceKills)); - msg.replace(this->INTERNAL_VICTIM_WINS_TAG, Jupiter::StringS::Format("%u", victim->wins)); - msg.replace(this->INTERNAL_VICTIM_LOSES_TAG, Jupiter::StringS::Format("%u", victim->loses)); - msg.replace(this->INTERNAL_VICTIM_BEACON_PLACEMENTS_TAG, Jupiter::StringS::Format("%u", victim->beaconPlacements)); - msg.replace(this->INTERNAL_VICTIM_BEACON_DISARMS_TAG, Jupiter::StringS::Format("%u", victim->beaconDisarms)); - msg.replace(this->INTERNAL_VICTIM_CAPTURES_TAG, Jupiter::StringS::Format("%u", victim->captures)); - msg.replace(this->INTERNAL_VICTIM_STEALS_TAG, Jupiter::StringS::Format("%u", victim->steals)); - msg.replace(this->INTERNAL_VICTIM_STOLEN_TAG, Jupiter::StringS::Format("%u", victim->stolen)); - msg.replace(this->INTERNAL_VICTIM_ACCESS_TAG, Jupiter::StringS::Format("%d", victim->access)); + PROCESS_TAG(this->INTERNAL_VICTIM_NAME_TAG, RenX::getFormattedPlayerName(victim)); + PROCESS_TAG(this->INTERNAL_VICTIM_RAW_NAME_TAG, victim->name); + PROCESS_TAG(this->INTERNAL_VICTIM_IP_TAG, victim->ip); + PROCESS_TAG(this->INTERNAL_VICTIM_UUID_TAG, victim->uuid); + PROCESS_TAG(this->INTERNAL_VICTIM_ID_TAG, Jupiter::StringS::Format("%d", victim->id)); + PROCESS_TAG(this->INTERNAL_VICTIM_CHARACTER_TAG, RenX::translateName(victim->character)); + PROCESS_TAG(this->INTERNAL_VICTIM_VEHICLE_TAG, RenX::translateName(victim->vehicle)); + PROCESS_TAG(this->INTERNAL_VICTIM_ADMIN_TAG, victim->adminType); + PROCESS_TAG(this->INTERNAL_VICTIM_PREFIX_TAG, victim->formatNamePrefix); + PROCESS_TAG(this->INTERNAL_VICTIM_GAME_PREFIX_TAG, victim->gamePrefix); + PROCESS_TAG(this->INTERNAL_VICTIM_TEAM_COLOR_TAG, RenX::getTeamColor(victim->team)); + PROCESS_TAG(this->INTERNAL_VICTIM_TEAM_SHORT_TAG, RenX::getTeamName(victim->team)); + PROCESS_TAG(this->INTERNAL_VICTIM_TEAM_LONG_TAG, RenX::getFullTeamName(victim->team)); + PROCESS_TAG(this->INTERNAL_VICTIM_PING_TAG, Jupiter::StringS::Format("%hu", victim->ping)); + PROCESS_TAG(this->INTERNAL_VICTIM_SCORE_TAG, Jupiter::StringS::Format("%.0f", victim->score)); + PROCESS_TAG(this->INTERNAL_VICTIM_CREDITS_TAG, Jupiter::StringS::Format("%.0f", victim->credits)); + PROCESS_TAG(this->INTERNAL_VICTIM_KILLS_TAG, Jupiter::StringS::Format("%u", victim->kills)); + PROCESS_TAG(this->INTERNAL_VICTIM_DEATHS_TAG, Jupiter::StringS::Format("%u", victim->deaths)); + PROCESS_TAG(this->INTERNAL_VICTIM_KDR_TAG, Jupiter::StringS::Format("%.2f", static_cast(victim->kills) / (victim->deaths == 0 ? 1.0f : static_cast(victim->deaths)))); + PROCESS_TAG(this->INTERNAL_VICTIM_SUICIDES_TAG, Jupiter::StringS::Format("%u", victim->suicides)); + PROCESS_TAG(this->INTERNAL_VICTIM_HEADSHOTS_TAG, Jupiter::StringS::Format("%u", victim->headshots)); + PROCESS_TAG(this->INTERNAL_VICTIM_VEHICLE_KILLS_TAG, Jupiter::StringS::Format("%u", victim->vehicleKills)); + PROCESS_TAG(this->INTERNAL_VICTIM_BUILDING_KILLS_TAG, Jupiter::StringS::Format("%u", victim->buildingKills)); + PROCESS_TAG(this->INTERNAL_VICTIM_DEFENCE_KILLS_TAG, Jupiter::StringS::Format("%u", victim->defenceKills)); + PROCESS_TAG(this->INTERNAL_VICTIM_WINS_TAG, Jupiter::StringS::Format("%u", victim->wins)); + PROCESS_TAG(this->INTERNAL_VICTIM_LOSES_TAG, Jupiter::StringS::Format("%u", victim->loses)); + PROCESS_TAG(this->INTERNAL_VICTIM_BEACON_PLACEMENTS_TAG, Jupiter::StringS::Format("%u", victim->beaconPlacements)); + PROCESS_TAG(this->INTERNAL_VICTIM_BEACON_DISARMS_TAG, Jupiter::StringS::Format("%u", victim->beaconDisarms)); + PROCESS_TAG(this->INTERNAL_VICTIM_CAPTURES_TAG, Jupiter::StringS::Format("%u", victim->captures)); + PROCESS_TAG(this->INTERNAL_VICTIM_STEALS_TAG, Jupiter::StringS::Format("%u", victim->steals)); + PROCESS_TAG(this->INTERNAL_VICTIM_STOLEN_TAG, Jupiter::StringS::Format("%u", victim->stolen)); + PROCESS_TAG(this->INTERNAL_VICTIM_ACCESS_TAG, Jupiter::StringS::Format("%d", victim->access)); } Jupiter::ArrayList &xPlugins = *RenX::getCore()->getPlugins();