• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[vJASS] Chat Command Manager

Deleted member 219079

D

Deleted member 219079

I've lots of old systems I used for my maps (abandoned them all lel). Maybe I submit more if this gets approved.

This is a chat command system, you use call CmdMan.create("cmd",function OnCommand) to create a permanent one, or store into integer to destroy later.

I added CmdMen afterwards, it's for Zinc mainly (lets say you have c,cam,camera,z,zoom, etc. which all do the same thing, you couldn't use an anonymous function without CmdMen). You use call CmdMen.create("cmd1 cmd2 cmd3 ...",function OnCommand) to create a permanent one, or store into integer to destroy later. (It is slow af, no reason to use in vanilla vJASS.)

JASS:
library CmdMan
    //! novjass //////////////////////////////////////////////////////////////////////////////
    //                                                                                      //
    //      Chat Command Manager by jondrean                                                //
    //      d:02.11.15 u:26.03.16                                                           //
    //                                                                                      //
    // Description:                                                                         //
    // This system is useful for saving Warcraft 3's memory; instead of setting up a new    //
    // trigger for each new command, it will all be handled under a single trigger. It'll   //
    // also automatically parse any arguments the user has given into a string array.       //
    //                                                                                      //
    // Usage:                                                                               //
        CmdMan.create(string,code)->CmdMan  // new command which calls given code           //
        .destroy()                          // destroys given command                       //
        CmdMen.create(string,code)->CmdMen  // multiple commands, separated with ARG_SEP    //
        .destroy()                          // destroys given commands                      //
    // Inside code:                                                                         //
        CmdMan.arg[n]->string               // returns <n>th argument (starts from 1)       //
        CmdMan.args->string                 // returns arguments, separated with ARG_SEP    //
        GetTriggerPlayer()->player          // returns the command author                   //
        GetEventPlayerChatString()->string  // returns the whole chat string                //
    //                                                                                      //
    // Notes:                                                                               //
    // • You can have same alias pointing at different codes                                //
    // • .arg[0] is the command itself, so NOT an actual argument                           //
    // • The next .arg[] after maximum is "", but the next after that might not be          //
    // • To quickly know if there's only the command itself given, use:                     //
        (CmdMan.arg[1]=="")->boolean                                                        //
    //                                                                                      //
    //! endnovjass ///////////////////////////////////////////////////////////////////////////
  
    globals
        private constant string KEY         = "-"       // commands have to be either "KEY <command>"
                                                        // or "KEY<command>"
                                                  
        private constant integer KEY_LENGTH = 1         // constants don't accept function calls, so
                                                        // you need to specify the length of KEY
                                                  
        private constant string ARG_SEP = " "           // this string is between each argument when
                                                        // using CmdMan.args/CmdMen
    endglobals
  
    static if(DEBUG_MODE)then
        globals
            private constant boolean FORGET_KEY = true  // forget key practice in debug mode
        endglobals
    endif
  
    private module Init//module init so you can already use the system at your own onInit
        private static method onInit takes nothing returns nothing
            local integer n=0
            loop
                call TriggerRegisterPlayerChatEvent(t,Player(n),"",false)
                exitwhen(n==11)
                set n=n+1
            endloop
            call TriggerAddCondition(t,Condition(function thistype.onChat))
            call DisableTrigger(t)
        endmethod
    endmodule
    struct CmdMan extends array
        private static trigger t=CreateTrigger()
        private static trigger tT=CreateTrigger()//temp
        private static string array cmd
        private static filterfunc array filt
        private static integer M=-1
        readonly static string array arg
        private static string S
        static method operator args takes nothing returns string
            local integer n=2
            if(arg[1]=="")then
                return ""
            endif
            set S=arg[1]
            loop
                exitwhen (arg[n]=="")
                set S=S+ARG_SEP+arg[n]
                set n=n+1
            endloop
            return S
        endmethod
        private static method onChat takes nothing returns boolean
            local string s=GetEventPlayerChatString()
            local integer n=StringLength(s)
            local integer m=0
            local string c
            local string txt=""
            static if(FORGET_KEY)then
                set s=SubString(s,0,n)
                //! runtextmacro CMDMAN_PARSE()
            else
                if(SubString(s,0,KEY_LENGTH)==KEY)then
                    set s=SubString(s,KEY_LENGTH,n)
                    set n=n-KEY_LENGTH
                    //! runtextmacro CMDMAN_PARSE()
                endif
            endif
            set s=""
            return false
        endmethod
        //! textmacro CMDMAN_PARSE
            loop
                exitwhen(n==0)
                set c=SubString(s,0,1)
                if(c!=" ")then
                    set txt=txt+c
                elseif(txt!="")then
                    set arg[m]=txt
                    set m=m+1
                    set txt=""
                endif
                set s=SubString(s,1,n)
                set n=n-1
            endloop
            if(txt!="")then
                set arg[m]=txt
                set m=m+1
                set txt=""
            endif
            set arg[m]=""
            loop
                if(cmd[n]==arg[0])then
                    call TriggerAddCondition(tT,filt[n])
                endif
                exitwhen(n==M)
                set n=n+1
            endloop
            call TriggerEvaluate(tT)
            call TriggerClearConditions(tT)
            set c=""
            set txt=""
        //! endtextmacro
        method destroy takes nothing returns nothing
            call DestroyFilter(filt[this])
            set filt[this]=filt[M]
            set filt[M]=null
            set cmd[this]=cmd[M]
            set cmd[M]=""
            if(M==0)then
                call DisableTrigger(t)
            endif
            set M=M-1
        endmethod
        static method create takes string cmd, code c returns thistype
            set M=M+1
            if(M==0)then
                call EnableTrigger(t)
            endif
            set thistype.cmd[M]=cmd
            set thistype.filt[M]=Filter(c)
            return M
        endmethod
        implement Init
    endstruct
  
    private module InitMen//module init so you can already use the system at your own onInit
        private static method onInit takes nothing returns nothing
            local integer n=0
            loop
                set thistype(n).next=n+1
                exitwhen(n==8189)
                set n=n+1
            endloop
        endmethod
    endmodule
    struct CmdMen extends array
        private CmdMan c
        private thistype next
        method destroy takes nothing returns nothing
            local integer n=this
            loop
                call this.c.destroy()
                set n=this.next
                exitwhen(n==0)
                set this.next=thistype(0).next
                set thistype(0).next=this
                set this=n
            endloop
        endmethod
        static method create takes string cmd, code f returns thistype
            local integer l=StringLength(cmd)
            local string txt=""
            local string c
            local string array arr
            local integer m=-1
            local thistype this
            loop
                exitwhen(l==0)
                set c=SubString(cmd,l-1,l)
                if(c!=ARG_SEP)then
                    set txt=c+txt
                elseif(txt!="")then
                    set m=m+1
                    set arr[m]=txt
                    set txt=""
                endif
                set l=l-1
            endloop
            set c=""
            if(txt!="")then
                set m=m+1
                set arr[m]=txt
                set txt=""
            endif
            loop
                exitwhen(m==-1)
                if(l==0)then
                    set this=thistype(0).next
                else
                    set thistype(l).next=thistype(0).next
                endif
                set l=thistype(0).next
                set thistype(0).next=thistype(l).next
                set thistype(l).c=CmdMan.create(arr[m],f)
                set arr[m]=""
                set m=m-1
            endloop
            set thistype(l).next=0
            return this
        endmethod
        implement InitMen
    endstruct
  
endlibrary

Example - KillUnit - command:
JASS:
//! zinc
library MyLib {
 
    group g=CreateGroup();
 
    private function onInit() {
        CmdMan.create("ku",function(){
            unit FoG;
            GroupEnumUnitsSelected(g,GetTriggerPlayer(),null);
            while(true){
                FoG=FirstOfGroup(g);
                if(FoG==null)break;
                KillUnit(FoG);
                GroupRemoveUnit(g,FoG);
            }
        });
    }
 
}
//! endzinc

Edit: Corrected indentation
 

Deleted member 219079

D

Deleted member 219079

Ye.

No requirements and parses command into parameters.

Weird though, I didn't find equivalent when I posted this.
 
@edo494 could you jump in and make some statement, as you are the author of the other command library? :)

No requirements and parses command into parameters.
Requirements can make sense sometimes, too, but yeh.. ; the code parsing is not really specifily for this system, but more using zinc (edo's could, too, probably) ;p
 
Level 23
Joined
Apr 16, 2012
Messages
4,041
JASS:
    static if(DEBUG_MODE)then
        globals
            private constant boolean FORGET_KEY = true  // forget key practice in debug mode
        endglobals
    endif

this only works on Cohadar's(if you want to static if a global variable on Vexorian's, you have to put it inside struct).

This resource does basically the same thing, the API is subjectivelly better(even tho slightly less intuitive), the distinctive difference is that mine can handle "-kill -camera 1000 -dosomething" while yours must have different object. Also the names arent really all that good(CmdMem, CmdMan).

You preparse the stuff ("-a b c d" in your will be arg[1] = "b", arg[2] = "c", arg[3] = "d"), while I dont(GetChatCommandString would return "b c d"), which can be both good and bad.

Other than that it achieves exactly the same thing.

Sorry for super late response, but I dont really open hive even daily currently(sometimes I will open it four times a day, sometimes not once in two days)
 

Deleted member 219079

D

Deleted member 219079

this only works on Cohadar's
You're saying it doesn't compile for you? You need to have latest JassHelper (0.A.2.B): JassHelper 0.A.2.B - A vJass and Zinc 2 Jass compiler - Wc3C.net

Also the names arent really all that good(CmdMem, CmdMan).
My management oriented systems are all *Man:s, I later on implement CmdMen because I started using Zinc. I think it is very systematic, you know what to expect by looking at the name.

You preparse the stuff
You can retrieve original command line by CmdMan.args or GetEventPlayerChatString, difference being that spaces are normalized in the former.

I think that, as inspired from C++, you made StringIterator, then wanted to make application for it to demonstrate its capabilities. If you remove the requirement I don't see how this submission would be beneficial addition to hive and would vote this to be GY'd.
 

Deleted member 219079

D

Deleted member 219079

StringIterator has more uses than just ChatCommand.
Oh I'm sure. You don't need it to something as simple as chat command management. You used it in your system just for the sake of using it. If you address this I'm open for having this graveyarded, this is what I tried to say before.

It compiles, the variable is never removed because globals are moved before static ifs are evaluated.
I see now, good catch. :D I tried this now and seems to work:
JASS:
globals
    private constant boolean FORGET_KEY = DEBUG_MODE  // forget key practice in debug mode
endglobals

CmdMen does not show me what to expect at all
Feel free to suggest alternative name lol, I don't really care about it that much.
 
I think he meant to prefer even longer but more readable names, like "CmdMan" -> "CommandManager".
I personaly do, as well, also "tT", "M" are just often hard to follow in reading.
Plus sometimes no line breaks between functions, etc, missing spaces between maths operators, after parameters, which decrease readability a bit, and is not really important anyways.

I see the globals thing is not changed, yet-- please do changes next days if you want to keep something updated, and I will also review it next days.
 

Deleted member 219079

D

Deleted member 219079

I rather write this from scratch. I will have plenty of time on the latter half of March.
 
Top