• 🏆 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!

[JASS] Sync Data Of Player Other Than Host

Status
Not open for further replies.
Level 31
Joined
Jul 10, 2007
Messages
6,306
So this syncing script doesn't work. It stores the name of the local player in the game cache, then tries to sync player 1 up with the rest. The local player name is still displayed (sync fails).

JASS:
struct tester extends array
    public static constant integer SYNC_PLAYER = 1
    public static string data
    public static integer file
    public static gamecache syncer
    public static player sync
    public static string pid
    
    private static method test takes nothing returns nothing
        set tester.syncer = InitGameCache("hello")
        set tester.sync = Player(tester.SYNC_PLAYER)
        set tester.pid = I2S(GetPlayerId(tester.sync))
        set tester.data = GetPlayerName(GetLocalPlayer())
        //set file = FileOpen("test", false)
        //call FileWrite(file, data)
        //call FileClose(file)

        if GetLocalPlayer()==tester.sync then
          call StoreString(tester.syncer, "data", tester.pid, tester.data)
        endif

        call TriggerSyncStart()
        if GetLocalPlayer()==tester.sync then
            call SyncStoredString(tester.syncer, "data", tester.pid)
        endif
        call TriggerSyncReady()

        set tester.data = GetStoredString(tester.syncer,"data",tester.pid)

        call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, tester.data)
    endmethod
    
    private static method onInit takes nothing returns nothing
        call TimerStart(CreateTimer(), 0, false, function thistype.test)
    endmethod
endstruct

My goal should be obvious from the above ^_^. My problem is that the player name displayed is still that of the local player, not that of player 1.

The first player to respond is obviously player 1... so I don't get why it doesn't sync o_O.
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
When I talk JASS, I talk 0-11 =). Sorry if it confused you : P.

If I meant red, I woulda said Player 0 ^_-.

Also, given the decently advanced nature of the code, I think it should be apparent that I know how to use players : P. I've also written a few guides on vJASS/JASS/cJASS (some of them ranging up to 24 chapters) that went over manual OO programming in vJASS, manual interface programming, syntax, API, and etc. People usually come to me when they have questions on how to do something in JASS : P.


Anyways, the above code looks 100% right to me... I don't get why it isn't working... it really should be working, /gah.

JASS:
        if GetLocalPlayer()==tester.sync then
            call SyncStoredString(tester.syncer, "data", tester.pid)
        endif

A sync command is sent out to the host, who in turn broadcasts it to the rest of the players. GetHost works because the host is the fastest one to send a sync command to itself, meaning that it broadcasts its value to the players.

Sync, from my understanding, runs upon its first sync (the first sync to make it wins). Since Blue is the only player that's sending a sync command, that means it should win... however, what is happening is the sync command isn't being sent to the host or being broadcast, it's just staying on blue...

It doesn't matter whether a sync command is local or not because it will always be sent to the host and broadcasted.. if it's local, that just means it's going to be the only one sent, meaning that it will sync the value of the local player to the host and then the rest of the players in the game.

So given all of that, I'm at a loss as to why my code isn't working ; P.
 
Level 26
Joined
Aug 18, 2009
Messages
4,097
Maybe the auditors/host must be prepared for the incoming sync? After all, the fastest has to be decided and thus, the following ones need to be ignored. I do not know whether it's not possible to have more than one syncs of one key in a sync-block but the function is called >Trigger<SyncStart/Ready, so I doubt it's even directly for the sync of gamecaches.

And btw why do you need to sync the player names? They are set in the beginning of the game, you can retrieve them via GetPlayerName, own SetPlayerName changes can be logged on own. Is there some ingame name spoofer tool that is not seen by GetPlayerName?
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
->And btw why do you need to sync the player names?
I don't, but I do want the script to work so that I can use it for other purposes, like save/load with RtC file IO ^_^.

->but the function is called >Trigger<SyncStart/Ready, so I doubt it's even directly for the sync of gamecaches.

It was made with gamecaches in mind, but can probably be used for other things : |.

One thing I was thinking of is syncing and then syncing again, the second sync being for all. I'm really unsure of what to do to get this working. Your theory sounds plausible (one I was thinking of as well, which is why I was thinking of multiple syncs). What I could probably do is a TriggerSleepAction within the sync block for other players (0, enough for delay) followed by a sync, that way they'll be ready or w/e. Not sure ^_-.
 
Level 19
Joined
Feb 4, 2009
Messages
1,313
maybe you can abuse a local wait (or something more complicated with timers) to make a specific player win the sync race
something like
if GetLocalPlayer() == player then
wait
endif
sync

but maybe this will just desync x)
(try both gametime and normal wait)

if a player lags or has a higher ping than the wait duration this will cause bugs though

if waits don't work you could try to occupy a pc with mass spam actions without any effect on the gameplay like
if GetLocalPlayer() ....
loop
endloop
endif

if loop/endloop does not take long enough because of the opperation limit add some code which takes longer
don't know if trigger execute works around the op limit in this case (probably not but didn't test it)
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
Bribe just posted this brilliant code saying it works
JASS:
struct tester extends array
    private static method onInit takes nothing returns nothing
        local integer i = 11
        local boolean array playing
        set playing[GetPlayerId(GetLocalPlayer())] = true
        
        call TriggerSleepAction(0.)
        
        loop
            if (playing[i]) then
                call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, GetPlayerName(Player(i)) + " is playing")
            endif
            exitwhen i == 0
            set i = i - 1
        endloop
    endmethod
endstruct

Much better than using a gamecache. I'm still not quite sure why it works, but he says it does. I'll have to test it myself.

OHHHH, I get it now!!! TriggerSleepAction syncs up across all players!! If each player is running on its own thread and the threads are later syncd together, then... but why should each player require its own thread via ExecuteFunc or TriggerEvaluate or TriggerExecute? Or does TriggerEvaluate only reset op limit? Hm... lots of questions now, hehehe..

My thought is, why is ExecuteFunc needed? Shouldn't the original thread work just as well?

I am most def going to use this to update PlayerManager as well.
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
I really don't get why you find this useful. The exact same code (omitting the TriggerSleepAction commands) would function exactly the same. Also take note that TriggerSleepAction may not even have anything to do with player syncing; this native is inaccurate even in a single-player game, where sync-time would be 0.
 
Status
Not open for further replies.
Top