Dismiss Notice
60,000 passwords have been reset on July 8, 2019. If you cannot login, read this.

Reforged [DESYNC] - 2 Possible causes found

Discussion in 'Patch & Reforged Discussion' started by Blarto, Mar 9, 2020.

  1. Blarto

    Blarto

    Joined:
    Jan 17, 2010
    Messages:
    150
    Resources:
    1
    Spells:
    1
    Resources:
    1
    Topic of jass vs lua (why/when jass is better than lua, and why/when lua is better than jass), and what Blizzard did wrong is outside the scope of this topic. I only wish to report desync cause so other people know this might happen to them, and also gather some potential solutions. I can explain it in Discord or private message. TLDR 1.31 completely broke Warcraft custom gaming for 1-2 months.
     
  2. DracoL1ch

    DracoL1ch

    Joined:
    Dec 12, 2010
    Messages:
    2,037
    Resources:
    2
    Tutorials:
    2
    Resources:
    2
    nah dont be a crykiddy, blizzard told they will patch agressively, soon you gonna see everything being fine, just give them more time to polish it
     
  3. kleinerhauck

    kleinerhauck

    Joined:
    Jun 1, 2008
    Messages:
    300
    Resources:
    8
    Maps:
    8
    Resources:
    8
    hi blarto, i appreciate this information. if they wont fix it officially - would your approach also work for maps using gui triggers?
     
  4. Blarto

    Blarto

    Joined:
    Jan 17, 2010
    Messages:
    150
    Resources:
    1
    Spells:
    1
    Resources:
    1
    For Force Bridge or other Bridge issue
    They fixed the force bridge bridge issue (one of the desyncs mentioned).

    For Walkable Destructable issue
    If you have any Blizzard model assets that are tagged "walkable" the map is at risk of desyncing no matter what. This includes all of the stock platforms (elevators, bridges, floor switches, etc) found in the editor object editor. I fixed this issue by opening old MPQ file and using the classic models as my walkables (custom destructables) instead of the Blizzard ones.

    For GetLocationZ related issue
    First confirm that you are using GetLocationZ before asking yourself if whatever desyncs are happening are caused by this issue.

    Simplest way is to find GetLocationZ references and replace them with 0.0. This will thematically break whatever is relying on it but at-least the map won't desync because of this anymore. I honestly don't think GUI maps rely on Z axis collision. Only think I can think of that is widely affected are the advanced missile jass libraries.

    To find if you have any of these GetLocationZ calls, you'll need to save map, then open it in MPQ editor and find the war3map.j file, extract that and open with a text editor, and do a search to see (editor converts all GUI triggers to jass in that file unless lua is selected). For lua it will be war3map.lua or something like that.

    I cannot think of replacement functionality solution that's simply a "plug and play" (for example like the BoundSentinel jass library). There's just too much Z data to send across all players. There is a 2 stage solution but it requires some knowledge of jass/vjass or lua. I am currently testing it now.
     
  5. Blarto

    Blarto

    Joined:
    Jan 17, 2010
    Messages:
    150
    Resources:
    1
    Spells:
    1
    Resources:
    1
    UPDATE

    Testing on a multi stage solution to create a "Safe" GetLocationZ went successful.

    Unfortunately since this problem is very niche (most people should just remove all GetLocationZ calls that set stuff like unit height, or replace them with 0), I won't bother discussing on how to do this in lab section unless there are multiple people who wish to know the process. This is a 3 stage solution (best I could think of), and it takes about 40 seconds to load the Z data of a 256x256 grid into the map script proper without any noticable frame issues.

    This is mainly used for Immersive Missiles/Projectiles that travel in the 3 dimensional plane properly and do not use and new Blz APIs (and instead use old xefx). I think this is the only way to have 3 Dimensional collision spheres, which I think are not a thing for 99.99% of maps, so yeah, use Blz api for new Missiles instead of xefx to eliminate the need for this alltogether.

    Here is a sample of terrain it creates and injects into map script. This is zoomed out base64 encoding of all Z coordinates found in a 512x512 grid for a 256x256 map (map size of 512x512 will have a 1024x1024 grid) --- Yes all of it are actual strings such as "aabbccdd...." representing the height map. The GetZ function call that is created as a result of this is relatively optimised, but not 100% accurate. First and last stages are done in (v)jass. middle stage is done in java (very basic and can be rewritten in any other language with file + copy pastable console access). REQUIRES Blz API (1.31+?) to work.

    upload_2020-3-24_0-15-24.png
     
    Last edited: Mar 24, 2020
  6. Jilaer

    Jilaer

    Joined:
    Aug 27, 2019
    Messages:
    7
    Resources:
    0
    Resources:
    0
    upload_2020-3-29_15-15-32.png Is it like this? But too much data needs to be synchronized. What should I do?
     
  7. Blarto

    Blarto

    Joined:
    Jan 17, 2010
    Messages:
    150
    Resources:
    1
    Spells:
    1
    Resources:
    1
    Do experiment to see if sending 256x256 integers (around 65500 values) is viable using Reforged netcode. I'm guessing it is not. You can use compression to reduce the amount of integers by around 60%. Syncing using GameCache takes 0.1 seconds or so, I don't know how much time the new API takes but I'm guessing its around same. And also, there is a limit to how much you can sync per second, and given the nature of what GetZ is used for, its a bad solution.

    What do you need GetLocationZ for?

    if its for missiles you have several choices
    1) assume Z = 0 at all times and recode missile library to "look passable" by messing with its GetFlyHeight/SetFlyHeight Values.
    2) create new missile library that is moving the "effect" handle using new Blz apis instead of xefx (will take you several weeks). effects are local so setting on those Z won't desync for different Z values per players.
    3) Use my solution which scans the entire map before play-time, and saves all Z points in script, then when map loads at actual play time, calculates them over 30 seconds to create 1,000,000 z points. This solution is terrible for anything larger than 256x256.

    If its for something else you should tell us, because I honestly can't think of anything other than a "set xefx.z = myz" in missile code scenario.
     
  8. Jilaer

    Jilaer

    Joined:
    Aug 27, 2019
    Messages:
    7
    Resources:
    0
    Resources:
    0
    upload_2020-3-30_12-0-37.png I just want a missile library. Maybe I got it wrong before.I thought different positions of effects would be desync.So this code is safe, right?
     
  9. Blarto

    Blarto

    Joined:
    Jan 17, 2010
    Messages:
    150
    Resources:
    1
    Spells:
    1
    Resources:
    1
    BlzGetUnitZ is also "local" according to the comments in the common.j file. This means it might return different values per player.

    But since you are manipulating effect position, it should be fine. But I have not tested this. you have to test this yourself with someone.

    Something like this will do the trick and confirm desync or not.
    Code (Text):

    local e = AddSpecialEffect("",0,0)
    if GetLocalPlayer() == Player(0) then
        BlzSetSpecialEffectPosition(e,1,1,1)
    else
        BlzSetSpecialEffectPosition(e,2,2,2)
    end
     
    I know for sure the thing below doesn't desync, which leads me to believe effects are local.
    Code (Text):

    local e
    local s
    if GetLocalPlayer() == Player(0) then
        s = "mymodel.mdl"
    else
        s = ""
    end
    e = AddSpecialEffect(s,0,0)
     
     
  10. Zwiebelchen

    Zwiebelchen

    Joined:
    Sep 17, 2009
    Messages:
    7,014
    Resources:
    12
    Models:
    5
    Maps:
    1
    Spells:
    1
    Tutorials:
    1
    JASS:
    4
    Resources:
    12
    Missile does nothing with GetLocationZ that desyncs. It only uses GetLocationZ for setting flyHeight of units which does not cause or require net traffic and is purely visual and does not desync on asynchronous data.

    GetLocationZ was never synchronous in the past 15 years. What are you even talking about?

    So, no, saying that using Missile in your map causes desyncs is simply false because we already know for 15 years that you cant use GetLocationZ for anything gameplay relevant.
     
  11. Blarto

    Blarto

    Joined:
    Jan 17, 2010
    Messages:
    150
    Resources:
    1
    Spells:
    1
    Resources:
    1
    Please do not spread misinformation or lies.

    Missile (hive's missile library - [vJASS] - Missile) uses SetUnitFlyHeight which is dependent on GetLocationZ. Here is an excerpt. Last line desyncs for certain terrains (reforged vs classic)

    Code (Text):

                    call MoveLocation(LOC, newX, newY)
                    set terrainZ = GetLocationZ(LOC)
                    set pitch = p.alpha
                    if 0. == height and 0. == pitch then
                        set z = p.z - terrainZ
                    else
                        set z = p.z - terrainZ + p.slope*point
                        if 0. != height and target == null then
                            set z = z + (4*height*point*(d - point)/p.square)
                            set pitch = pitch - Atan(((4*height)*(2*point - d))/p.square)*bj_RADTODEG
                        endif
                    endif
                    // Update the pitch angle of the dummy unit.
                    if GetUnitTypeId(u) == Missile_DUMMY_UNIT_ID then
                        call SetUnitAnimationByIndex(u, R2I(pitch + 90.5))
                    endif
                   
                    // Move the missile dummy via native.
                    call SetUnitFlyHeight(u, z, 0.) // <- desync <-
     
     
  12. TriggerHappy

    TriggerHappy

    Code Moderator

    Joined:
    Jun 23, 2007
    Messages:
    3,793
    Resources:
    22
    Spells:
    11
    Tutorials:
    2
    JASS:
    9
    Resources:
    22
    Moving effects locally should be fine. You can even move units locally as long as they don't have collision, ignore pathing, and a few other things. Although I don't really see a reason to do such a thing anymore.

    I'm not exactly sure why
    SetUnitFlyHeight
    would desync. You would assume it's purely a visual effect however it has been "known" in the community to desync with terrain deformations for a while now and with Reforged the problem is probably just magnified due to the different graphic modes. I suppose it's possible the desyncs have something to do with fly height affecting vision which in turn might cause a unit to aggro something he's not supposed to but I don't imagine that scenario happening too often.

    Anyway I think all of the plausible solutions have already been discussed and in general only use GetLocationZ for visual-only systems.
     
  13. Blarto

    Blarto

    Joined:
    Jan 17, 2010
    Messages:
    150
    Resources:
    1
    Spells:
    1
    Resources:
    1
    I was confused about this as well. It might be because the height field is tied to the unit's pathing/movement (to contrast setting unit art fields such as color locally doesn't desync).

    There are no Getters for unit's "art" fields as far as I know. But for unit's height field, there is a getter (GetUnitFlyHeight). I think script/game engine tries to resolve the field for the Getter to work, which probably what causes the desync.

    Edit: its worth noting getLocationZ desync happens when unit is actually issued an order to move somewhere. if you fire a missile that desyncs and stand still, sometimes it doesnt desync until some movement event happens.
     
  14. TriggerHappy

    TriggerHappy

    Code Moderator

    Joined:
    Jun 23, 2007
    Messages:
    3,793
    Resources:
    22
    Spells:
    11
    Tutorials:
    2
    JASS:
    9
    Resources:
    22
    Well, in that case I would try disabling a unit's pathing and collision while you are modifying it's height. You can give it the Ghost (Visible) ability along with
    SetUnitPathing
    . If you are just setting fly height of dummy units for effect purposes then I would switch to the new Blz effect API.
     
  15. Blarto

    Blarto

    Joined:
    Jan 17, 2010
    Messages:
    150
    Resources:
    1
    Spells:
    1
    Resources:
    1
    What causes desyncs in my end are xefx dummies. I'd try doing what you suggested out of curiosity if it fixes it but I already fixed the issue by adding a Synced GetZ function.

    using BlzAPI is good but requires rewrite of the (missile) system. Not to mention it requires 1.31+ which is dead. Most of the active map community is currently on 1.26-1.29.
     
  16. Zwiebelchen

    Zwiebelchen

    Joined:
    Sep 17, 2009
    Messages:
    7,014
    Resources:
    12
    Models:
    5
    Maps:
    1
    Spells:
    1
    Tutorials:
    1
    JASS:
    4
    Resources:
    12
    Which is exactly what I wrote. Do you even read or are you just hacking away on you keyboard? SetUnitFlyHeight locally does not desync unless someone uses the specific getter for FlyHeight for something else.

    I never used terrain deformations though. They have been widely known for being unstable anyway.

    I use Missile in Gaias Retaliation and it doesnt desync at all even in Reforged mode.
    (Gaias does suffer desync problems since Reforged but ONLY on map init, which has nothing to do with Missile)
     
    Last edited: Apr 4, 2020
  17. Blarto

    Blarto

    Joined:
    Jan 17, 2010
    Messages:
    150
    Resources:
    1
    Spells:
    1
    Resources:
    1
    Does your map use steep cliffs or walkable destructables that have different models based on reforged or classic?

    GetLocationZ only returns different values for these conditions. Try firing missiles over steep cliffs or reforgedxclassic destructables. And yes, you actually have to have purchased reforged and tested it yourself or with someone who purchased it to test desyncs,

    You are guilty of your own trashtalk.

    Edit: here is a test case you can try, example of a steep cliff and fire several missiles.
    upload_2020-4-4_11-16-28.png
     
    Last edited: Apr 4, 2020
  18. Zwiebelchen

    Zwiebelchen

    Joined:
    Sep 17, 2009
    Messages:
    7,014
    Resources:
    12
    Models:
    5
    Maps:
    1
    Spells:
    1
    Tutorials:
    1
    JASS:
    4
    Resources:
    12
    I know that GetLocationZ is async in these cases. It has always been.
    What Im saying is that this doesnt matter because setting a flyheight locally is save in most usecases.
     
  19. Blarto

    Blarto

    Joined:
    Jan 17, 2010
    Messages:
    150
    Resources:
    1
    Spells:
    1
    Resources:
    1
    Use cases which Missile.j constructs flying over steep cliffs or reforged doodads, with a classic wc3 user, are not part of.

    As stated multiple times, this issue affects old maps the most. These maps assume GetLocationZ is safe for all (nearly all) cases, and for the longest while it was, but reforged rendering engine made it completely unsafe so this function should be avoided now, unless dealing with local-only code. Heck, if you're just a GUI user, avoid that function entirely and never use any code that relies on it unless it was proven to work properly.

    Best way to fix old maps is just Find-and-replace all GetLocationZ(?) with 0.0 and call it a day. Fast and easy fix. But if the map has LightningEx calls it becomes a bit harder since those would be completely visually broken if that replacement is done (but GetLocationZ is safe to use for those so skipping them in the find-replace is prudent).
     
  20. Zwiebelchen

    Zwiebelchen

    Joined:
    Sep 17, 2009
    Messages:
    7,014
    Resources:
    12
    Models:
    5
    Maps:
    1
    Spells:
    1
    Tutorials:
    1
    JASS:
    4
    Resources:
    12
    I'm out of this discussion. You just simply refuse to understand. SetUnitFlyHeight does NOT desync. GetLocationZ was always unstable since vanilla wc3. It does not break old maps when used wrong because these maps have always been broken.