HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

how works the multiplayer code execution?

11-26-2009, 02:54 PM#1
mystafox
Hi all, happy coding

here is my problem :

Collapse JASS:
globals
    integer array P1Array1
    integer P1Variable1
    ...
endglobals

function Trig_Untitled_Trigger_001_Actions takes nothing returns nothing
    local boolean P1Bool
    ...
    Do some stuff : init locals etc...
    ...
    set P1Bool = MyHeavyFunctionReachOpLimit ( some args )
    ...
    Do some actions depending on P1Bool
    ...
    clean some stuff
endfunction

//===========================================================================
function InitTrig_Untitled_Trigger_001 takes nothing returns nothing
    set gg_trg_Untitled_Trigger_001 = CreateTrigger(  )
    call TriggerRegisterPlayerUnitEventSimple( gg_trg_Untitled_Trigger_001, Player(0), EVENT_PLAYER_UNIT_CONSTRUCT_START )
    call TriggerAddAction( gg_trg_Untitled_Trigger_001, function Trig_Untitled_Trigger_001_Actions )
endfunction

I have a trigger that fires when a unit from a specific player is create. After some heavy calculation, the unit is create or destroyed. All the modified data and such are tied to the player. The heavy calculation just do some basic math stuff and array access.

Now, this works good for single player. But what if i do the same for 8 players?
As i understand jass, scripts are executed by all players, so when a unit for player x is created all players must perform the calculations (So there will be 8 calcuations just to find out the same result that only 1 calculation needs, not to mention this result is only important for 1 player :s)
From what i understand GetLocalPlayer() will force the execution to one player, but as i use globals it will desync the players. Even if the globals are never accessed by the other players? Is there no way to resynch a global?
11-26-2009, 03:49 PM#2
Anitarf
I don't see a problem with all game clients doing the calculation. There is no easy way to sync globals, all methods that exist are not instant, but cause a delay in code execution.
11-26-2009, 03:57 PM#3
grim001
You can use globals (even allocate structs) and do calculations asynchronously without any issues, as long as the values stored in those globals are only used for local operations.
11-26-2009, 04:25 PM#4
DioD
This wont make execution faster and may lead to "hard to find" bugs.

Leave as is as.
11-26-2009, 04:54 PM#5
mystafox
Quote:
This wont make execution faster
Why?
If The 8 players builds one unit at the same time then all 8 game client have to perform 8 HugeFunc instead of one .... how dont that make execution faster?

also from what grim001 says the only issue with changing globals with GetLocalPlayer() is if the global is then accessed by any other part of the script not using GetLocalPlayer(), right ?

thx for the replies
11-26-2009, 04:59 PM#6
grim001
Quote:
Originally Posted by mystafox
also from what grim001 says the only issue with changing globals with GetLocalPlayer() is if the global is then accessed by any other part of the script not using GetLocalPlayer(), right ?

as long as you only use those globals inside GetLocalPlayer() blocks, and you only perform no-network-traffic actions inside the GetLocalPlayer() blocks, you should avoid any desyncs.
11-26-2009, 05:56 PM#7
mystafox
Quote:
as long as you only use those globals inside GetLocalPlayer() blocks, and you only perform no-network-traffic actions inside the GetLocalPlayer() blocks, you should avoid any desyncs.

How do i know what actions need network-traffic?
I am still a little confuse about how it works. Its sounds like globals act a lot like locals (for players), and if something in the traffic is not matching then it will desync.
Still i want to know why it wont make the execution faster
11-26-2009, 06:07 PM#8
Anitarf
In practice, situations where this would matter do not happen. We can not comment further without knowing what exactly you are trying to do.
11-26-2009, 08:53 PM#9
mystafox
i'm doing a system to prevent a player to place a blocking tower in a TD map (mazing one with multiple waypoints).
It works a lot like the basic stuff in the first post, if player 1 start a building unit then check if the tower is blocking or not. That's the P1Bool, if it's not blocking then update P1Array1 otherwise remove the unit.
When doing the check i'm reaching the op-limit, so i did some triggersleepaction and now its works good but it take some time (<1 sec but still you can notice). The operation are very simple as consists only of basic math (+,-,*,/), array acces and storage of integers.The time comes from the sleep (that's what i think because it doesnt slow the game ).
But i wonder if it is viable in multiplayer games, hence the ask of local execution of code and globals sync.
11-27-2009, 12:01 AM#10
grim001
That's not the kind of thing you should use GetLocalPlayer() or local calculations for. You're probably doing something wrong if you're hitting the oplimit, I suggest posting code for critique.
11-27-2009, 02:17 AM#11
DioD
Such check will cause your machine stop building tower but others will build it or vise versa.
11-27-2009, 03:57 AM#12
mystafox
Quote:
Such check will cause your machine stop building tower but others will build it or vise versa.
why that? Now i know i should not use GetLocalPlayer() or local calculations (isnt that the same?). But if i dont use such techniques and just stick with my code why would that happen?

anyway here is the code, it's only for one player as i'm learning jass and it was a test to see if it was possible to do.
For multiple players, instead of only one variable maze, mazeDL, stack and spos there would be one for each player. The rest is the same with corresponding variables.
Collapse JASS:
globals
    integer array maze  //0=path , 1= waypoint, 2 = wall
    integer array mazeDL  //0=free , 1=being build
    integer array stack
    integer spos = -1
    constant integer WP = 11
    constant integer NUMCOLS = 58
    constant integer NUMROWS = 58
    constant integer START = 9 * NUMCOLS + 1
    
    real originX
    real originY
    constant real MAZEX = 1856
    constant real MAZEY = -1856
    constant integer MAZECELL = 64
    
    constant integer LOOPPAUSE = 200//3200
    
    //boolean isBlocking = FALSE
endglobals

function InitMaze takes nothing returns nothing
    local integer i = 0
    set originX = GetRectCenterX( GetWorldBounds() )
    set originY = GetRectCenterY( GetWorldBounds() )
    
    loop //upper && lower walls
        exitwhen i >= NUMCOLS  
        set maze[i] = 2 
        set maze[i + NUMCOLS] = 2 
        set maze[i + NUMCOLS * (NUMROWS - 2)] = 2
        set maze[i + NUMCOLS * (NUMROWS - 1)] = 2
        set i = i+1
    endloop
    set i = 0
    loop //left & right walls
        exitwhen i >= NUMROWS  
        set maze[i * NUMCOLS ] = 2
        set maze[i * NUMCOLS + 1] = 2
        set maze[(i+1) * NUMCOLS - 2 ] = 2
        set maze[(i+1) * NUMCOLS - 1 ] = 2
        set i = i+1
    endloop
    // clean START,END and set the waypoints
    //set maze[8 * NUMCOLS ] = 0
    set maze[8 * NUMCOLS + 1] = 0
    //set maze[9 * NUMCOLS + 1] = 0
    set maze[9 * NUMCOLS + 1] = 1
    
    set maze[(NUMROWS - 7 + 1) * NUMCOLS  - 2] = 0
    set maze[(NUMROWS - 8 + 1) * NUMCOLS  - 2] = 0
    set maze[(NUMROWS - 9 + 1) * NUMCOLS  - 2] = 0
    set maze[(NUMROWS - 10 + 1) * NUMCOLS  - 2] = 1
    set maze[(NUMROWS - 11 + 1) * NUMCOLS  - 2] = 0
    set maze[(NUMROWS - 12 + 1) * NUMCOLS  - 2] = 0
    
    set maze[ 8 * NUMCOLS + 11] = 1
    set maze[ 8 * NUMCOLS + 31] = 1
    set maze[ 9 * NUMCOLS + 45] = 1
    
    set maze[ 23 * NUMCOLS + 11] = 1
    set maze[ 23 * NUMCOLS + 30] = 1
    set maze[ 23 * NUMCOLS + 44] = 1
    
    set maze[ 37 * NUMCOLS + 11] = 1
    set maze[ 37 * NUMCOLS + 27] = 1
    set maze[ 48 * NUMCOLS + 27] = 1
    
    
endfunction


function IsBlocked takes integer a, integer b, integer c, integer d returns boolean
    local integer array tmpMaze // 0= not flooded, 1=flooded
    local integer wpVisited = 0
    local integer tmpLoc = -1

    local integer loopCount = 1
    
    debug call BJDebugMsg( "Process started" )
    set tmpMaze[a] = 1
    set tmpMaze[b] = 1
    set tmpMaze[c] = 1
    set tmpMaze[d] = 1

    set spos = 0
    set stack[spos] = START
    
    loop //op limit
        debug call BJDebugMsg( "loop " + I2S(loopCount) + " : wp=" + I2S(wpVisited) + " spos=" + I2S(spos) )
        
        
        if( loopCount - loopCount/LOOPPAUSE * LOOPPAUSE == 0) then
            call TriggerSleepAction(0.0)
        endif
        set loopCount = loopCount + 1
        
        exitwhen wpVisited >= WP or spos < 0
        set tmpLoc = stack[spos]
        set spos = spos - 1
        if tmpMaze[tmpLoc] < 1 and maze[tmpLoc] < 2 and mazeDL[tmpLoc] < 1 then
            set tmpMaze[tmpLoc] = 1
            set wpVisited = wpVisited + maze[tmpLoc]
            debug call BJDebugMsg( "    flood : " + I2S(tmpLoc) + " (" /*
                     */ + R2S( (tmpLoc - R2I(tmpLoc/NUMCOLS)*NUMCOLS ) * MAZECELL + MAZEX)/*
                     */ +"," + R2S(R2I(tmpLoc/NUMCOLS) * -MAZECELL + MAZEY) + ")" )
            //set spos = spos + 1
            set stack[spos+4] = tmpLoc + 1
            //set spos = spos + 1
            set stack[spos+1] = tmpLoc - 1
            //set spos = spos + 1
            set stack[spos+3] = tmpLoc + NUMCOLS
            //set spos = spos + 1
            set stack[spos+2] = tmpLoc - NUMCOLS 
            set spos = spos + 4
        endif
    endloop
    debug call BJDebugMsg( "loop end with value : " + I2S(WP) + " " + I2S(wpVisited) )
    //set isBlocking = (WP != wpVisited)
    return WP != wpVisited
endfunction

function Trig_Begin_building_Actions takes nothing returns nothing
    local boolean isBlocking
    local integer lowerRight
    local real unitX = GetUnitX(GetTriggerUnit())
    local real unitY = GetUnitY(GetTriggerUnit())
    local effect tmpE
    
    set lowerRight = NUMCOLS * R2I( RAbsBJ(unitY - MAZEY)/MAZECELL ) + R2I(RAbsBJ(unitX - MAZEX)/MAZECELL )

    call DisplayTimedTextToForce( GetPlayersAll(), 5.00, "Construction Started at " + I2S(lowerRight) )
    
    set mazeDL[lowerRight] = 1
    set mazeDL[lowerRight - 1] = 1
    set mazeDL[lowerRight - NUMCOLS] = 1
    set mazeDL[lowerRight - NUMCOLS - 1] = 1
    
    set isBlocking = IsBlocked(lowerRight, lowerRight - 1, lowerRight - NUMCOLS, lowerRight - NUMCOLS - 1)
    
    //call IsBlocked(lowerRight, lowerRight - 1, lowerRight - NUMCOLS, lowerRight - NUMCOLS - 1)
    
    
    if ( isBlocking ) then
        set tmpE = AddSpecialEffect("Abilities\\Spells\\Human\\DispelMagic\\DispelMagicTarget.mdl" , unitX, unitY)
        call DestroyEffect( tmpE )
        call RemoveUnit( GetTriggerUnit() )
        call DisplayTimedTextToForce( GetPlayersAll(), 5.00, "Tower was blocking" )
    else
        call DisplayTimedTextToForce( GetPlayersAll(), 5.00, "Tower is not blocking" )
        set maze[lowerRight] = 2
        set maze[lowerRight - 1] = 2
        set maze[lowerRight - NUMCOLS] = 2
        set maze[lowerRight - NUMCOLS - 1] = 2
    endif
    
    set mazeDL[lowerRight] = 0
    set mazeDL[lowerRight - 1] = 0
    set mazeDL[lowerRight - NUMCOLS] = 0
    set mazeDL[lowerRight - NUMCOLS - 1] = 0
    

    
endfunction

//===========================================================================
function InitTrig_Begin_building takes nothing returns nothing
    set gg_trg_Begin_building = CreateTrigger(  )
    call TriggerRegisterPlayerUnitEventSimple( gg_trg_Begin_building, Player(0), EVENT_PLAYER_UNIT_CONSTRUCT_START )
    call TriggerAddAction( gg_trg_Begin_building, function Trig_Begin_building_Actions )
endfunction