]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Client commands: register
authorTimePath <andrew.hardaker1995@gmail.com>
Mon, 21 Dec 2015 05:50:19 +0000 (16:50 +1100)
committerTimePath <andrew.hardaker1995@gmail.com>
Mon, 21 Dec 2015 05:50:19 +0000 (16:50 +1100)
Weapons: weapon_find command to show waypoints

qcsrc/client/commands/cl_cmd.qc
qcsrc/client/commands/cl_cmd.qh
qcsrc/client/main.qc
qcsrc/common/animdecide.qh
qcsrc/common/weapons/all.qc
qcsrc/lib/net.qh
qcsrc/server/command/cmd.qc
qcsrc/server/weapons/selection.qc

index 63e0c56126f7394c8ffd8eacbab9a9d194a229c6..be3ac56450b170dcc0806bcca54bc16bd1556a8d 100644 (file)
@@ -493,57 +493,45 @@ void LocalCommand_(int request)
 // ==================================
 
 // Normally do not hard code aliases for these, instead create them in commands.cfg... also: keep in alphabetical order, please ;)
-#define CLIENT_COMMANDS(request, arguments) \
-       CLIENT_COMMAND("blurtest", LocalCommand_blurtest(request), "Feature for testing blur postprocessing") \
-       CLIENT_COMMAND("boxparticles", LocalCommand_boxparticles(request, arguments), "Spawn particles manually") \
-       CLIENT_COMMAND("create_scrshot_ent", LocalCommand_create_scrshot_ent(request), "Create an entity at this location for automatic screenshots") \
-       CLIENT_COMMAND("debugmodel", LocalCommand_debugmodel(request, arguments), "Spawn a debug model manually") \
-       CLIENT_COMMAND("handlevote", LocalCommand_handlevote(request, arguments), "System to handle selecting a vote or option") \
-       CLIENT_COMMAND("hud", LocalCommand_hud(request, arguments), "Commands regarding/controlling the HUD system") \
-       CLIENT_COMMAND("localprint", LocalCommand_localprint(request, arguments), "Create your own centerprint sent to yourself") \
-       CLIENT_COMMAND("find", LocalCommand_find(request, arguments), "Search through entities for matching classname") \
-       CLIENT_COMMAND("mv_download", LocalCommand_mv_download(request, arguments), "Retrieve mapshot picture from the server") \
-       CLIENT_COMMAND("sendcvar", LocalCommand_sendcvar(request, arguments), "Send a cvar to the server (like weaponpriority)") \
-       /* nothing */
+CLIENT_COMMAND(blurtest, "Feature for testing blur postprocessing") { LocalCommand_blurtest(request); }
+CLIENT_COMMAND(boxparticles, "Spawn particles manually") { LocalCommand_boxparticles(request, arguments); }
+CLIENT_COMMAND(create_scrshot_ent, "Create an entity at this location for automatic screenshots") { LocalCommand_create_scrshot_ent(request); }
+CLIENT_COMMAND(debugmodel, "Spawn a debug model manually") { LocalCommand_debugmodel(request, arguments); }
+CLIENT_COMMAND(handlevote, "System to handle selecting a vote or option") { LocalCommand_handlevote(request, arguments); }
+CLIENT_COMMAND(hud, "Commands regarding/controlling the HUD system") { LocalCommand_hud(request, arguments); }
+CLIENT_COMMAND(localprint, "Create your own centerprint sent to yourself") { LocalCommand_localprint(request, arguments); }
+CLIENT_COMMAND(find, "Search through entities for matching classname") { LocalCommand_find(request, arguments); }
+CLIENT_COMMAND(mv_download, "Retrieve mapshot picture from the server") { LocalCommand_mv_download(request, arguments); }
+CLIENT_COMMAND(sendcvar, "Send a cvar to the server (like weaponpriority)") { LocalCommand_sendcvar(request, arguments); }
 
 void LocalCommand_macro_help()
 {
-       #define CLIENT_COMMAND(name, function, description) \
-               { if (strtolower(description) != "") { LOG_INFO("  ^2", name, "^7: ", description, "\n"); } }
-
-       CLIENT_COMMANDS(0, 0);
-       #undef CLIENT_COMMAND
+       FOREACH(CLIENT_COMMANDS, true, LAMBDA(LOG_INFOF("  ^2%s^7: %s\n", it.m_name, it.m_description)));
 }
 
-bool LocalCommand_macro_command(int argc)
+bool LocalCommand_macro_command(int argc, string command)
 {
-       #define CLIENT_COMMAND(name, function, description) \
-               { if (name == strtolower(argv(0))) { function; return true; } }
-
-       CLIENT_COMMANDS(CMD_REQUEST_COMMAND, argc);
-       #undef CLIENT_COMMAND
-
+       string c = strtolower(argv(0));
+       FOREACH(CLIENT_COMMANDS, it.m_name == c, LAMBDA(
+               it.m_invokecmd(CMD_REQUEST_COMMAND, NULL, argc, command);
+               return true;
+       ));
        return false;
 }
 
 bool LocalCommand_macro_usage(int argc)
 {
-       #define CLIENT_COMMAND(name, function, description) \
-               { if (name == strtolower(argv(1))) { function; return true; } }
-
-       CLIENT_COMMANDS(CMD_REQUEST_USAGE, argc);
-       #undef CLIENT_COMMAND
-
+       string c = strtolower(argv(1));
+       FOREACH(CLIENT_COMMANDS, it.m_name == c, LAMBDA(
+               it.m_invokecmd(CMD_REQUEST_USAGE, NULL, argc, "");
+               return true;
+       ));
        return false;
 }
 
 void LocalCommand_macro_write_aliases(int fh)
 {
-       #define CLIENT_COMMAND(name, function, description) \
-               { if (strtolower(description) != "") { CMD_Write_Alias("qc_cmd_cl", name, description); } }
-
-       CLIENT_COMMANDS(0, 0);
-       #undef CLIENT_COMMAND
+       FOREACH(CLIENT_COMMANDS, true, LAMBDA(CMD_Write_Alias("qc_cmd_cl", it.m_name, it.m_description)));
 }
 
 
@@ -587,7 +575,7 @@ void GameCommand(string command)
        }
        // continue as usual and scan for normal commands
        if (GenericCommand(command)                                    // handled by common/command/generic.qc
-           || LocalCommand_macro_command(argc)                        // handled by one of the above LocalCommand_* functions
+           || LocalCommand_macro_command(argc, command)               // handled by one of the above LocalCommand_* functions
            || MUTATOR_CALLHOOK(CSQC_ConsoleCommand, s, argc, command) // handled by a mutator
           ) return;
 
index ba3151c43c545f6ffa59b9ae589eeec493a6a18e..23d72ff60e9020eab24806688f32e80c08d1d96e 100644 (file)
@@ -1,13 +1,27 @@
 #ifndef CLIENT_COMMANDS_CL_CMD_H
 #define CLIENT_COMMANDS_CL_CMD_H
-// ==============================================
-//  CSQC client commands code, written by Samual
-//  Last updated: December 17th, 2011
-// ==============================================
 
 void Cmd_HUD_SetFields(int);
 void Cmd_HUD_Help();
 
 // used by common/command/generic.qc:GenericCommand_dumpcommands to list all commands into a .txt file
 void LocalCommand_macro_write_aliases(int fh);
+
+REGISTRY(CLIENT_COMMANDS, BITS(7))
+#define CLIENT_COMMANDS_from(i) _CLIENT_COMMANDS_from(i, NULL)
+REGISTER_REGISTRY(CLIENT_COMMANDS)
+REGISTRY_SORT(CLIENT_COMMANDS)
+
+#define CLIENT_COMMAND(id, description) \
+       CLASS(clientcommand_##id, Command) \
+               ATTRIB(clientcommand_##id, m_name, string, #id); \
+       ATTRIB(clientcommand_##id, m_description, string, description); \
+       ENDCLASS(clientcommand_##id) \
+    REGISTER(CLIENT_COMMANDS, CMD_CL, id, m_id, NEW(clientcommand_##id)); \
+       METHOD(clientcommand_##id, m_invokecmd, void(int request, entity caller, int arguments, string command))
+
+STATIC_INIT(CLIENT_COMMANDS_aliases) {
+       FOREACH(CLIENT_COMMANDS, true, LAMBDA(localcmd(sprintf("alias %1$s \"%2$s %1$s ${* ?}\"\n", it.m_name, "qc_cmd_cl"))));
+}
+
 #endif
index 6b5cf6463fcd6bf2f393f0aac3880b28dc66c982..05a11080b98bd458e22244109d06f3ded6af6c8b 100644 (file)
@@ -759,7 +759,7 @@ void CSQC_Ent_Update(bool isnew)
                if (isnew) this.classname = it.netname;
                if (autocvar_developer_csqcentities)
             LOG_INFOF("CSQC_Ent_Update(%d) at %f with this=%i {.entnum=%d, .enttype=%d} t=%s (%d)\n", isnew, savetime, this, this.entnum, this.enttype, this.classname, t);
-               done = it.m_read(this, isnew);
+               done = it.m_read(this, NULL, isnew);
                break;
        ));
        time = savetime;
@@ -849,7 +849,7 @@ bool CSQC_Parse_TempEntity()
        FOREACH(TempEntities, it.m_id == nTEID, LAMBDA(
                if (autocvar_developer_csqcentities)
                        LOG_INFOF("CSQC_Parse_TempEntity() nTEID=%s (%d)\n", it.netname, nTEID);
-               return it.m_read(NULL, true);
+               return it.m_read(NULL, NULL, true);
        ));
 
        if (autocvar_developer_csqcentities)
index 578a30f68bccab793dbadf9e6e8b956be4dc677e..39ca54ff2f7783514755385f4e3af49b557d54c9 100644 (file)
@@ -26,8 +26,8 @@ ENDCLASS(Animation)
 REGISTRY(Animations, BITS(8))
 REGISTER_REGISTRY(Animations)
 #define Animations_from(id) _Animations_from(id, NULL)
-#define WriteAnimation(to, it) WriteRegistry(Animations, to, it)
-#define ReadAnimation() ReadRegistry(Animations)
+#define WriteAnimation(to, it) WriteRegistered(Animations, to, it)
+#define ReadAnimation() ReadRegistered(Animations)
 #define REGISTER_ANIMATION(id, framenames) \
        .vector anim_##id; \
        REGISTER(Animations, ANIM_##id, m_id, NEW(Animation)) { \
index 7d107fd61d5a34d345541cb1697e12dd0e3ca30d..07ae7585163abd8ac4ce8954e99f395704196024 100644 (file)
@@ -588,6 +588,60 @@ void wframe_send(entity actor, entity weaponentity, vector a, bool restartanim)
 }
 #endif
 
+REGISTER_NET_C2S(w_whereis)
+#ifdef SVQC
+void Weapon_whereis(Weapon this, entity cl);
+NET_HANDLE(w_whereis, bool)
+{
+       Weapon wpn = ReadRegistered(Weapons);
+       if (wpn != WEP_Null) Weapon_whereis(wpn, sender);
+       return true;
+}
+#else
+void w_whereis(Weapon this)
+{
+       int channel = MSG_C2S;
+       WriteHeader(channel, w_whereis);
+       WriteRegistered(Weapons, channel, this);
+}
+CLIENT_COMMAND(weapon_find, "Show spawn locations of a weapon")
+{
+       switch (request)
+       {
+               case CMD_REQUEST_COMMAND:
+               {
+                       string s = argv(1);
+                       if (s == "all")
+                       {
+                               FOREACH(Weapons, it != WEP_Null, w_whereis(it));
+                               return;
+                       }
+                       if (s == "unowned")
+                       {
+                               FOREACH(Weapons, it != WEP_Null && !(STAT(WEAPONS) & it.m_wepset), w_whereis(it));
+                               return;
+                       }
+                       FOREACH(Weapons, it != WEP_Null && it.netname == s,
+                       {
+                               w_whereis(it);
+                               return;
+                       });
+               }
+               default:
+               {
+                       LOG_INFOF("Incorrect parameters for ^2%s^7\n", "weapon_find");
+               }
+               case CMD_REQUEST_USAGE:
+               {
+                       LOG_INFO("\nUsage:^3 cl_cmd weapon_find weapon\n");
+                       LOG_INFO("  Where 'weapon' is the lowercase weapon name, 'all' or 'unowned'.\n");
+                       return;
+               }
+       }
+}
+#endif
+
+
 #endif
 
 #endif
index 0c0f814e87e6a1113387c40e1fc8d847fae59782..9782ba31311caa0de35cb8ae4c78d736049a6b77 100644 (file)
@@ -7,8 +7,8 @@
 
 .string netname;
 .int m_id;
-.bool(entity this, bool isNew) m_read;
-#define NET_HANDLE(id, param) bool Net_Handle_##id(entity this, param)
+.bool(entity this, entity sender, bool isNew) m_read;
+#define NET_HANDLE(id, param) bool Net_Handle_##id(entity this, entity sender, param)
 
 
 #ifdef CSQC
@@ -155,7 +155,7 @@ STATIC_INIT(C2S_Protocol_renumber) { FOREACH(C2S_Protocol, true, it.m_id = i); }
 
        int ReadByte();
 
-       void Net_ClientCommand(string command)
+       void Net_ClientCommand(entity sender, string command)
        {
                // command matches `c2s "(.+)"`
                string buf = substring(command, argv_start_index(1) + 1, -2);
@@ -164,7 +164,7 @@ STATIC_INIT(C2S_Protocol_renumber) { FOREACH(C2S_Protocol, true, it.m_id = i); }
                for (int C2S; (C2S = ReadByte()) >= 0; )
                {
                        entity reader = C2S_Protocol_from(C2S);
-                       if (reader && reader.m_read && reader.m_read(NULL, true)) continue;
+                       if (reader && reader.m_read && reader.m_read(NULL, sender, true)) continue;
                        LOG_SEVEREF("Net_ClientCommand() with malformed C2S=%d\n", C2S);
                        return;
                }
@@ -212,8 +212,8 @@ STATIC_INIT(C2S_Protocol_renumber) { FOREACH(C2S_Protocol, true, it.m_id = i); }
                } MACRO_END
 #endif
 
-#define ReadRegistry(r) r##_from(Read_byte())
-#define WriteRegistry(r, to, it) Write_byte(to, it.m_id)
+#define ReadRegistered(r) r##_from(Read_byte())
+#define WriteRegistered(r, to, it) Write_byte(to, it.m_id)
 
 #define Read_byte() ReadByte()
 #define Write_byte(to, f) WriteByte(to, f)
index a454ff947dc4f7ca49b5bd5ef2aca8d59f097d18..319c204887e6fd64be83517c724c5cf93ec3073f 100644 (file)
@@ -752,7 +752,7 @@ void SV_ParseClientCommand(string command)
                case "prespawn": break;                            // handled by engine in host_cmd.c
                case "sentcvar": break;                            // handled by server in this file
                case "spawn": break;                               // handled by engine in host_cmd.c
-               case "c2s": Net_ClientCommand(command); return;    // handled by net.qh
+               case "c2s": Net_ClientCommand(this, command); return; // handled by net.qh
 
                default:
                        if (SV_ParseClientCommand_floodcheck()) break; // "true": continue, as we're not flooding yet
index abd1d9f319a611b592fcc2f609cc97d844cf96a0..4b96e1f9dc85ef7e6e3a7c2775489e852bac5d4f 100644 (file)
@@ -17,6 +17,28 @@ void Send_WeaponComplain(entity e, float wpn, float type)
        WriteByte(MSG_ONE, type);
 }
 
+void Weapon_whereis(Weapon this, entity cl)
+{
+       if (!autocvar_g_showweaponspawns) return;
+       for (entity it = NULL; (it = findfloat(it, weapon, this.m_id)); )
+       {
+               if (it.classname == "droppedweapon" && autocvar_g_showweaponspawns < 2)
+                       continue;
+               if (!(it.flags & FL_ITEM))
+                       continue;
+               entity wp = WaypointSprite_Spawn(
+                       WP_Weapon,
+                       1, 0,
+                       NULL, it.origin + ('0 0 1' * it.maxs.z) * 1.2,
+                       cl, 0,
+                       NULL, enemy,
+                       0,
+                       RADARICON_NONE
+               );
+               wp.wp_extra = this.m_id;
+       }
+}
+
 bool client_hasweapon(entity cl, Weapon wpn, float andammo, bool complain)
 {
        float f = 0;
@@ -77,27 +99,7 @@ bool client_hasweapon(entity cl, Weapon wpn, float andammo, bool complain)
                if (weaponsInMap & WepSet_FromWeapon(wpn))
                {
                        Send_WeaponComplain(cl, wpn.m_id, 1);
-
-                       if(autocvar_g_showweaponspawns)
-                       {
-                               for(entity e = world; (e = findfloat(e, weapon, wpn.m_id)); )
-                               {
-                                       if(e.classname == "droppedweapon" && autocvar_g_showweaponspawns < 2)
-                                               continue;
-                                       if(!(e.flags & FL_ITEM))
-                                               continue;
-                                       entity wp = WaypointSprite_Spawn(
-                                               WP_Weapon,
-                                               1, 0,
-                                               world, e.origin + ('0 0 1' * e.maxs.z) * 1.2,
-                                               cl, 0,
-                                               world, enemy,
-                                               0,
-                                               RADARICON_NONE
-                                       );
-                                       wp.wp_extra = wpn.m_id;
-                               }
-                       }
+                       Weapon_whereis(wpn, cl);
                }
                else
                {