HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Sync Problems

07-22-2007, 03:56 AM#1
PandaMine
I am currently having a sync problem, as many people may already know Captain Griffein and myself have figured out a way to differentiate between replays and actual game play. However since the function that detects this uses cameras, you need to take care with sync methods. Here is what i have for the following function

Collapse JASS:
function AMHS_IsInGame takes nothing returns boolean
local boolean output
local real currentx 
local real currenty
local real x
local real y
local integer counter = 1
local integer firstplayer

loop
exitwhen counter > 12
if GetPlayerSlotState(Player(counter - 1)) == PLAYER_SLOT_STATE_PLAYING then
set firstplayer = counter - 1
set counter = 13
endif
set counter = counter + 1
endloop

call PauseGame(true)
call TriggerSleepAction(0)
if Player(firstplayer) == GetLocalPlayer() then
set currentx = GetCameraTargetPositionX()
set currenty = GetCameraTargetPositionY()
endif
call SetCameraPositionForPlayer(Player(firstplayer),GetCameraTargetPositionX()+1,GetCameraTargetPositionY() + 1)

call TriggerSleepAction(0)
call PauseGame(false)
if Player(firstplayer) == GetLocalPlayer() then
set x = GetCameraTargetPositionX()
endif

//if Player(firstplayer) == GetLocalPlayer() then
if x == currentx + 1 then
set output = true
else
set output = false
endif
//endif


call SetCameraPositionForPlayer(Player(firstplayer),currentx,currenty)


set firstplayer = 0
set counter = 0
return output
endfunction 

Captain Griffen has already succesfuly edited the function using PitzerMikes 12bit function, however this method is very noticable because of the lossy compression. Im trying edit the same function but using the GetLocalPlayer method insted of the 12SyncBit function.

In the JASS are the highlighted lines that are the problem. TriggerSleep action creates a new thread that causes a desync, does anyone know any way around this. The desync does not happen straight away, instead it happens around 10-15 seconds later because of the wait. However the triggersleep action is essential because it is the only way to detect the difference between replays and actual gameplay. It might also be the PauseGame function however I cannot be certain

Also using triggers or timers instead of triggersleepaction wont work, the reason why triggersleepaction is used because it is unaffected by PauseGame, in other words it has to be used
07-22-2007, 07:34 AM#2
Toadcop
well =) i hate blizz sync methods + the desync at self.
they could add a native
Collapse JASS:
native ForceSync takes boolean force returns nothing
- well ^^ it means it will not Desync if data is not the same like by the host. that would be awesome... OR a normal way to sync datas (btw interesting if it possible to make such custom native...)

to the topic i don't see much sense what are you currently trying to do xD
07-22-2007, 07:50 AM#3
Captain Griffen
You could use AIAndy's SyncInteger function. I used Pitzer's cut down 12 bit one because it's faster, and I only need 12 bit accuracy.

Anyway, with that function, I'd say that if you have anything happening in that thread after the local TriggerSleepAction, then it'll desync. Set the output to a variable, then run actions after it with a timer.
07-23-2007, 05:03 AM#4
PandaMine
Were is AIAndy's sync function?
07-23-2007, 08:05 AM#5
Toadcop
Collapse JASS:
function SyncInteger takes player sync_p, integer unsynced returns integer
  local integer array source_int // the bits of the unsynced integer are stored in there
  local integer array target_int // the bits of the synced integer are stored in there
  local unit array sel_unit // the units used for the selection
  local integer i = 1
  local integer j = 0
  local integer sum = unsynced
  local group old_selection = CreateGroup()
  local unit u = null
  local integer bits_per_selection = 8 // that many bits are sent per selection
  local integer selection_num = 2 // that many times a selection is done
  local integer bits_number = selection_num * bits_per_selection // number of bits of integer used
  local timer t = CreateTimer()


  if bj_isSinglePlayer then
    return unsynced
  endif

  // separate integer in bits
  if sum < 0 then
    set source_int[0] = 1
    set sum = -sum
  else
    set source_int[0] = 0
  endif
  loop
    exitwhen i >= bits_number
    set source_int[i] = ModuloInteger(sum, 2)
    set sum = sum / 2
    set i = i + 1
  endloop

  // create units to select
  set i = 0
  loop
    exitwhen i >= bits_per_selection
    set sel_unit[i] = CreateUnitAtLoc( sync_p, 'nshf', GetPlayerStartLocationLoc(sync_p), bj_UNIT_FACING )
    set i = i + 1
  endloop

  // save old selection
  call SyncSelections()
  call GroupEnumUnitsSelected(old_selection, sync_p, null)

  // send the bits by selection
  set i = 0
  loop
    exitwhen i >= selection_num

    // write information
    if GetLocalPlayer() == sync_p then
      set j = 0
      call ClearSelection()
      loop
        exitwhen j >= bits_per_selection
        if source_int[i*bits_per_selection + j] == 0 then
          call SelectUnit(sel_unit[j], false)
        else
          call SelectUnit(sel_unit[j], true)
        endif
        set j = j + 1
      endloop
    endif

    // read information
    call TimerStart(t, 1, false, null)  // prevent wait bug
    loop
      exitwhen TimerGetRemaining(t) <= 0
      call TriggerSleepAction(0.5)
    endloop
    call SyncSelections()
    set j = 0
    loop
      exitwhen j >= bits_per_selection
      if IsUnitSelected(sel_unit[j], sync_p) then
        set target_int[i*bits_per_selection + j] = 1
      else
        set target_int[i*bits_per_selection + j] = 0
      endif
      set j = j + 1
    endloop

    set i = i + 1
  endloop

  // restore selection
  if GetLocalPlayer() == sync_p then
    call ClearSelection()
    loop
      set u = FirstOfGroup(old_selection)
      exitwhen u == null
      call SelectUnit(u, true)
      call GroupRemoveUnit(old_selection, u)
    endloop
  endif
  call SyncSelections()

  // remove units to select
  set i = 0
  loop
    exitwhen i >= bits_per_selection
    call RemoveUnit(sel_unit[i])
    set i = i + 1
  endloop

  // rebuild integer
  set i = bits_number - 1
  set sum = 0
  loop
    exitwhen i < 1
    set sum = 2 * sum + target_int[i]
    set i = i - 1
  endloop
  if target_int[0] != 0 then
    set sum = -sum
  endif


  return sum

endfunction
07-23-2007, 10:36 AM#6
MaD[Lion]
about the sync function, i see some triggersleepaction, so it means tat it will take time before it sync?
07-23-2007, 11:22 AM#7
Captain Griffen
Correct. And if the player selects anything it can mess up the integer. Disabling their user control during it works, though.

Actually, sync functions aren't instant in JASS either. They require a wait.
07-24-2007, 11:14 AM#8
MaD[Lion]
well but if u only need to sync with the host, then using SyncStoredInteger is better i think?
07-24-2007, 12:19 PM#9
Captain Griffen
Yes, I think so, but it won't always do the host.
07-26-2007, 12:51 PM#10
MaD[Lion]
why is that, the host is where everyone send their data to, so it should sync to the host
08-04-2007, 07:50 AM#11
PandaMine
Apperantly it doesnt always return the host, in very rare situations (usually if the host has a slow/laggy computer) it will sync some other player.
08-04-2007, 08:31 AM#12
Toadcop
btw i am working on "new" sync method and it works MUCH better ^^.
but in some cases worser... =)