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

[DESYNC] - 2 Possible causes found

Status
Not open for further replies.
Level 6
Joined
Jan 17, 2010
Messages
149
(UPDATE) they fixed Walkable destructables as of recent patch, but issues relating to GetLocationZ will remain.

GetLocationZ can return different values if Reforged user and Classic user are on same game and the following conditions apply:

1) you use platforms or destructables that are tagged "walkable" and use reforged assets (this means they have different local Z values as the models themselves will be different)
2) GetLocationZ sometimes returns different values on DEFAULT terrain for some reason (RIP)
+
3) you use a system (e.g Missile) which relies on some sort of GetZ that has GetLocationZ embedded in it, and/or use GetLocationZ to set global wc3 values such as unit height

=
Lets assume we use Missile jass library
Shoot 1 projectile across a platform or faulty terrain (again WTF), and reforged missile will have different Fly Height than Classic Missile

=
bye game



I can't be bothered to post screenshots and the map that you can replicate this with, at the moment. Just take my word for it.

I'm trying to figure out if there can be any viable replacement for GetLocationZ instead. And no, the BlzGetUnitZ are not viable as they are documented to be Local as well.

Most likely the only solution will be to synchronise (using TriggerHappy's sync library) player 1's GetLocationZ results across a predefined grid and use some sort of algorithm to "GetSmoothZ" or something.


Edit:
I found another cause related to force bridges (the transparent ones). Not sure if it applies to regular bridges. I don't know the mechanics of it yet. Shooting a projectile (Missile library, locust/xefx units) over to stuff located on it from water (all GetLocationZ calls removed) desyncs Reforged x Classic games.
 
Last edited:
Level 6
Joined
Jan 17, 2010
Messages
149
Yes. Standard procedure was to remove all shockwave and warstomp based spells to make GetLocationZ safe, since everyone pretty much had the same terrain data after doing that.

Reforged changed that.

My theory is that Reforged renders "Steep Terrain" differently. Steep Terrain is when you remove the smoothing factor in World Editor to make some really steep cliffs (useful to make high quality terrain).

A 256x256 map has 1,000,000 32x32 cells, which is approximately 32MB of Z data. Probably the best way I can think of right now to create a new GetZ is to just scan the map terrain file with a tool and generate jass/lua that saves the XYZ coordinates to a Hashtable for fast retrieval. Unfortunately that's about 100,000-250,000 lines of jass code on top of your script.
 
Last edited:

~El

Level 17
Joined
Jun 13, 2016
Messages
556
GetLocationZ was still unsafe between Windows/Mac players. It even warns you in common.j:
// This function is asynchronous. The values it returns are not guaranteed synchronous between each player.
// If you attempt to use it in a synchronous manner, it may cause a desync.
native GetLocationZ takes location whichLocation returns real

If you need synchronized data about the terrain height, then scan the map using one player and synchronize the data using `BlzSendSyncData`. It might take a while but it'll work. The approach you're suggesting will also work.

Also, I don't know where you got that 1,000,000 figure from. A 256x256 map has 257x257 height points. That's 66k points. You also don't -really- need full 32 bits of precision most likely, and can represent the height in your map using 16 bits. That's 128 kilobytes. Easily embeddable in Lua maps as a string which can be also easily decoded at init time.
 
Level 6
Joined
Jan 17, 2010
Messages
149
GetLocationZ was still unsafe between Windows/Mac players. It even warns you in common.j

The point was that it was safe before because terrain was rendered equally (most libraries relying on xefx + missile will have used GetLocationZ as there is no other way to make smooth projectiles otherwise). Because of equal terrain rendering, async GetLocationZ became effectively synced by default (as long as no shockwave or terrain deformation stuff happened). Yeah you might have lost some mac users, but the probability of a mac user in your game was nonexistent. Now with Reforged, every other person has desync potential.

Also, I don't know where you got that 1,000,000 figure from. A 256x256 map has 257x257 height points.

32 is the lowest "grid" size the world editor lets you see with "G" hotkey.

256x256 map has 32000x32000 cooridnates, 32000x32000 / 32 = 1000x1000 = 1,000,000 = 1 million integers recording the value of "Z" each point using 32bit each = 32mb (ish)

Some of the coordinates are trash due to boundaries.. reality is like maybe 28000x28000, and much of your map terrain may not be pathable in any way (so don't need to account for those places).

257x257 height points.
You need a fast GetZ function that returns proper value even if the XY coordinate does not align on one of those height points. To use 256x256 height points you'd need some sort of algorithm to smooth out/approximate the Z based on the 4 height points it is caught in between (hence my mention of "GetSmoothZ" function in first post). I don't think this is good as GetZ is used in Missile logic (i.e GetZ calls every 0.03215 seconds per missile). Its better to save 1,000,000 coordinates, and have the "smooth out" function just be R2I(x), R2I(y), and it will inevitabely fall on one of the 1,000,000 coordinates with acceptable accuracy.

Edit: come to think of it, you could probably adopt a hybrid approach, and extrapolate the 1,000,000 points at run time (at map init or slightly after map init) from the 65,550 or so points you get from 256x256 grid... 65k is still a ton of data to sync though. can probably cut this value by half or more since as you mentioned you only need 16 bits (pack 2-3 zs in 1 integer).

BlzSendSyncData
Syncing 1 million values is not viable IMO. Sync capability of wc3 have limit of about 5000 integers per minute unless they updated their net code greatly.
 
Last edited:

~El

Level 17
Joined
Jun 13, 2016
Messages
556
32 is the lowest "grid" size the world editor lets you see with "G" hotkey.

The heightmap in WC3 works on the tile grid, though, not on the 32x32 grid. All the in-between values can be interpolated linearly. Recording them is basically redundant data which you can get out of your 256x256 results anyway.

You need a fast GetZ function that returns proper value even if the XY coordinate does not align on one of those height points. To use 256x256 height points you'd need some sort of algorithm to smooth out/approximate the Z based on the 4 height points it is caught in between (hence my mention of "GetSmoothZ" function in first post). I don't think this is good as GetZ is used in Missile logic (i.e GetZ calls every 0.03215 seconds per missile). Its better to save 1,000,000 coordinates, and have the "smooth out" function just be R2I(x), R2I(y), and it will inevitabely fall on one of the 1,000,000 coordinates with acceptable accuracy.

If you want a fast approach, then you should just use Lua and stop thinking in the JASS way. This is trivial to do in Lua with performance that will not be a concern.

If you want to do this in JASS, hashtable performance will degrade with that many values in your hashmap.

The point was that it was safe before because terrain was rendered equally (most libraries relying on xefx + missile will have used GetLocationZ as there is no other way to make smooth projectiles otherwise). Because of equal terrain rendering, async GetLocationZ became effectively synced by default (as long as no shockwave or terrain deformation stuff happened). Yeah you might have lost some mac users, but the probability of a mac user in your game was nonexistent. Now with Reforged, every other person has desync potential.

Relying on undocumented, unsupported behaviours where the official API explicitly states that such usage is not supported, is a great way of shooting yourself in the foot. Which is exactly what's happening here.
 
Level 6
Joined
Jan 17, 2010
Messages
149
If you want to do this in JASS, hashtable performance will degrade with that many values in your hashmap.

Not all maps are convertable to lua. Some maps are 10 years old + with no map maker to update them (+ the dumbass map makers protected them so yeah bye map).

Also, how do you convert 100,000 lines of jass code to Lua without paying $30,000k+ for a developer to code & test all that shit anyway.


Relying on undocumented, unsupported behaviours where the official API explicitly states that such usage is not supported, is a great way of shooting yourself in the foot. Which is exactly what's happening here.

So official libraries by vexorian and hive's own Missile library that were tested and confirmed to work for 10+ years are a great way to shoot yourself in the foot. Not going to debate on whether they were correct to rely on GetLocationZ or not. It is what it is.

This isn't a thread to argue about jass vs lua or how to code your stuff. This failure is a regression issue introduced by Reforged x Classic compatibility.

Easiest way to counter this regression is just save your map to Classic-only with new editor (and "accept" new EULA as a consequence). That is, if you actually have access to the map. Also, by doing this you break compatibility with Netease and Gameranger, which combined are more popular than bnet.2.0 wc3. So yeah. Have to maintain separate versions. Balls. Easy to just keep to classic Jass and try to solve this issue with that tool I guess.

Edit: if you don't have access to the map you can try your luck by replacing GetLocationZ with 0.0 in the map's script with an MPQ editor. It will mess some logic up but atleas't you won't desync anymore. That's all I got for now.
 
Last edited:

~El

Level 17
Joined
Jun 13, 2016
Messages
556
I don't understand what is the exact issue you're jabbing at here.

Is the issue that this breaks old maps? If yes, then I agree. It's a bummer. But it's what happens when you rely on age-old bugs. Tons of other maps (especially those using typecasting hacks) also broke. Mapmakers fault for relying on unspecified behaviours.

Is the issue that the old trick doesn't work anymore in new maps? Then I disagree, because there are ways around it.

If you want to force classic-graphics mode on an old map, it should be sufficient to just replace the war3map.w3i file inside the map with a new one which has the correct flag for SD-only mode set.

You were going on about how to solve this issue, so I assumed you weren't talking about old maps.

Also, how do you convert 100,000 lines of jass code to Lua without paying $30,000k+ for a developer to code & test all that shit anyway.

This is disingenuous nonsense. All you need to do is to set your map into Lua mode. WorldEdit ships with a JASS->Lua transpiler, and that is in fact how it builds GUI triggers in Lua. It just transpiles the JASS code into Lua. There might be a few corner case bugs you will need to fix, but it definitely will not cost anyone $30,000.
 
Level 6
Joined
Jan 17, 2010
Messages
149
I don't understand what is the exact issue you're jabbing at here.

Is the issue that this breaks old maps? If yes, then I agree. It's a bummer. But it's what happens when you rely on age-old bugs. Tons of other maps (especially those using typecasting hacks) also broke. Mapmakers fault for relying on unspecified behaviours.

Just stop. 5 star system on hive using GetLocationZ -> [vJASS] - Missile all maps using it are now at risk. I don't care who's at fault and neither should you or anyone else reading this. It is what it is.

Is the issue that the old trick doesn't work anymore in new maps? Then I disagree, because there are ways around it.

If you want to force classic-graphics mode on an old map, it should be sufficient to just replace the war3map.w3i file inside the map with a new one which has the correct flag for SD-only mode set.
Have you tried this? do you know what happens? I'll tell you: Your computer crashes when trying to open map in wc3 1.32 reforged (100% CPU usage nothing works).

You were going on about how to solve this issue, so I assumed you weren't talking about old maps.
This issue applies to old and new maps. I provided some solutions but I'll make a more permanent one soon. Probably. (I.e a fast GetSyncedLocationZ)

This is disingenuous nonsense. All you need to do is to set your map into Lua mode. WorldEdit ships with a JASS->Lua transpiler, and that is in fact how it builds GUI triggers in Lua. It just transpiles the JASS code into Lua. There might be a few corner case bugs you will need to fix, but it definitely will not cost anyone $30,000.

Good to know. But even if it costs $1000 worth of your time, its still not a workload you should be doing, in my opinion. Your time is better spent on improving the map itself, and once you reach 50k lines, you're in a "damned if you do, damned if you don't" situation. For reference, $1000 is 3-14 days of software contracting depending on qualifications.
 
Last edited:

~El

Level 17
Joined
Jun 13, 2016
Messages
556
Good to know. But even if it costs $1000 worth of your time, its still not a workload you should be doing, in my opinion. Your time is better spent on improving the map itself, and once you reach 50k lines, you're in a "damned if you do, damned if you don't" situation. For reference, $1000 is 3-14 days of software contracting depending on qualifications.

Wow, I didn't know mappers contracted other people to develop their WC3 maps for thousands of dollars. Super relevant points you're making. /s

I don't understand the point of this thread. Is this a bug report? A demand to Blizzard to maintain backwards compatibility (they won't)? If not, why is this in the patch forum? If you're trying to come up with a solution, this should probably go in the lab.

You offered some solutions. I pointed out the errors in your estimates as well as the potential pitfalls you're going to face if you stick to JASS. And the fact that relying on specifically unsupported behaviour was dumb in the first place, and I don't understand how that library could've been approved by any code moderator worth their salt. You're getting oddly defensive about this.
 
Level 6
Joined
Jan 17, 2010
Messages
149
Wow, I didn't know mappers contracted other people to develop their WC3 maps for thousands of dollars. Super relevant points you're making. /s

I don't understand the point of this thread. Is this a bug report? A demand to Blizzard to maintain backwards compatibility (they won't)? If not, why is this in the patch forum? If you're trying to come up with a solution, this should probably go in the lab.

You offered some solutions. I pointed out the errors in your estimates as well as the potential pitfalls you're going to face if you stick to JASS. And the fact that relying on specifically unsupported behaviour was dumb in the first place, and I don't understand how that library could've been approved by any code moderator worth their salt. You're getting oddly defensive about this.

"Is this a bug report?" no.
"A demand to Blizzard to maintain backwards compatibility (they won't)" no.
"if not, why is this in the patch forum?" because its an issue introduced in wc3 reforged.
"this should probably go in the lab." no code = no lab.
"You offered some solutions" yes I did.
"I pointed out the errors in your estimates as well as the potential pitfalls" yes you did.
"And the fact that relying on specifically unsupported behaviour was dumb in the first place" nobody cares. Maps are desyncing and people lose interest in custom gaming. We all suffer.
"and I don't understand how that library could've been approved by any code moderator worth their salt." Let us know if you have a better Missile system, lua or jass or vjass, that doesn't rely on GetLocationZ to animate its flight path
"Super relevant points you're making." I'm saying you're wasting 1000 dollars worth of time to convert old jass to lua for little to no benefit, instead of just improving your map's features (user's mostly don't care about performance or what language map is written at)
"You're getting oddly defensive about this." get lost, drama monger.
 

~El

Level 17
Joined
Jun 13, 2016
Messages
556
"this should probably go in the lab." no code = no lab.

? The lab is a perfect place for technical discussions like this.

upload_2020-3-10_4-31-14.png


"and I don't understand how that library could've been approved by any code moderator worth their salt." Let us know if you have a better Missile system, lua or jass or vjass, that doesn't rely on GetLocationZ to animate its flight path

With the new natives it should be possible to stop using units for missiles. specialeffects can have local positions that will not desync, thus allowing you to use GetLocationZ in a way that doesn't need to be synchronized. I'm not going to do this for you, though, because I have better things to do.

"Super relevant points you're making." I'm saying you're wasting 1000 dollars worth of time to convert old jass to lua for little to no benefit, instead of just improving your map's features (user's mostly don't care about performance or what language map is written at)

I thought people developed maps during their free time, which, naturally, they don't get paid for. If the choice is between working on your maps features, or making your map work at all, I think I know which one I'll take.
Also, hot take, but sometimes people develop for their own pleasure, not for the pleasure of other people.

"You're getting oddly defensive about this." get lost, drama monger.
Oh no, you poor snowflake. Are you mad because you can't handle a little forum confrontation?
 

Attachments

  • upload_2020-3-10_4-31-12.png
    upload_2020-3-10_4-31-12.png
    11.7 KB · Views: 76
Level 6
Joined
Jan 17, 2010
Messages
149
So I'll address some the proposed "solutions" in more detail before signing off:

With the new natives it should be possible to stop using units for missiles. specialeffects can have local positions that will not desync, thus allowing you to use GetLocationZ in a way that doesn't need to be synchronized. I'm not going to do this for you, though, because I have better things to do.
This works but you'll have to rewrite all of the missile libraries + xefx. And nobody is going to do this for you, which I estimate will take around 2-4 weeks worth of work to develop and iron out all the bugs (replace xefx +create new missile library). Performance wise it will be worse on moving the missile (instead of SetUnitX, you'll need to setFX_X + record X to get GetFX_X, since SFX are local), but better on creating the missile (CreateUnit vs CreateSFX). Overall effort is not worth it. Probably worth it for new maps though. There is supposingly a new ParticleAPI too but I'm not sure its exposed in 1.32 (it is on Netease, DZ api etc).

If you want to force classic-graphics mode on an old map, it should be sufficient to just replace the war3map.w3i file inside the map with a new one which has the correct flag for SD-only mode set.
Worth repeating that this trick crashes your computer. Do not do it. I tested multiple variants of this trick.

Wow, I didn't know mappers contracted other people to develop their WC3 maps for thousands of dollars.
Oh if only you knew more about this. Talking about this is against new EULA though... Probably.

? The lab is a perfect place for technical discussions like this.
No it isn't. This thread is to let people know (that is, for their benefit) what possible reason could happening if their map desyncs. That is, Missile system with GetLocationZ to regulate its height. Nobody cares about the Lab section. This section is more visible, which serves this purpose just fine.

Good job continuing to derail your own thread further, though.
This is a typical troll behaviour to attempt to enrage someone and have them start flaming or lose their shit or something. Notice how this guy never offered any applicable solutions or advice aside from "git gud at wc3 editor" or "remake your map" or "sucks to be you".
 
Level 18
Joined
Jan 1, 2018
Messages
728
which I estimate will take around 2-4 weeks worth of work to develop
2 weeks to write a missile library? rofl

Performance wise it will be worse on moving the missile
Source?

Worth repeating that this trick crashes your computer. Do not do it. I tested multiple variants of this trick.
This map supposedly uses this 'trick' as well, haven't seen anyone complain about it.

Nobody cares about the Lab section.
I like the lab...

This is a typical troll behaviour to attempt to enrage someone and have them start flaming or lose their shit or something.
:peasant-popcorn:
 
Level 6
Joined
Jan 17, 2010
Messages
149
2 weeks to write a missile library? rofl, Source?

Don't underestimate how long it takes you to write some system piece of code that must be optimal and work under all circumstances (where 1 small glitch can break an entire map playthrough and force a restart).

Yea its roughly 3 day for dev 2 weeks for testing (1-hr/day live games) + 3 more days fixing bugs over these 2 weeks

Source?

I actually written one and it took about half as long (i aborted due deciding original xefx is better for regression and performance reasons). You have to rewrite xefx to use effect handle, as well as missile library to use new xefx, and handle all regressions from. We had a few testing sessions on many use cases to iron out some bugs.

Performance is worse because SetX/Y for unit inlines with vexopt to 1 line call whereas SetX for BlzSetSfxX will not inline because you need another line to record the x/y (BlzSetSfx is local so there is no synced GetX/Y). Treating units as a datastructure also has some other implications, such as you can attach multiple effects to 1 unit to make missile trails (a common use case of attaching ribbons). If you relied on SetSfxX/Y you'd have to update each and every one of them, whereas with old xefx you just moved the unit. This means there are less stress on SetX/Y with unit-based xefx than moving effects.

Of course if you use lua it doesn't matter as lua engine performs better than the jassVM due to lua runtime being "closer" to the OS and consequentially closer to the processor/memory stack.

Edit: you can achieve optimal performance by removing dependency on xefx all-together (effectively in lining effect native in missiles), but you'll introduce regression issues for already existing code that assumes Missile structs have xefx. In the aforementioned library I written, I decided against it because i'd have to update around 100+ missiles + basically lose support for wc 1.26-1.28 (no BlzSetSFX natives there).

I like the lab...
Good. If I make a jass/lua library to have a SyncedGetZ, you'll find it there.

This map supposedly uses this 'trick' as well, haven't seen anyone complain about it.
I don't think so. It uses new native API (as evidenced from screenshots + UI difference), so they probably just saved their map in 1.32.
This doesn't work if the map you're trying to play is not yours and "protected". Copying .w3i directly to mpq file (and/or deleting old .w3i) either corrupts the map or make it crash your computer.

If anyone knows a way to have this trick work I would be most interested, and so are many other map makers.
 
Last edited:
Level 18
Joined
Jan 1, 2018
Messages
728
Don't underestimate how long it takes you to write some system piece of code that must be optimal and work under all circumstances (where 1 small glitch can break an entire map playthrough and force a restart).

Yea its roughly 3 day for dev 2 weeks for testing (1-hr/day live games) + 3 more days fixing bugs over these 2 weeks
I know coding takes time and it's easy to underestimate, but when you say 2 weeks I'm assuming that's 8hrs per day. "2 weeks testing" and "fixing bugs over these 2 weeks" doesn't sound like you're working full-time.

I actually written one and it took about half as long (i aborted due deciding original xefx is better for regression and performance reasons). You have to rewrite xefx to use effect handle, as well as missile library to use new xefx, and handle all regressions from. We had a few testing sessions on many use cases to iron out some bugs.

Performance is worse because SetX/Y for unit inlines with vexopt to 1 line call whereas SetX for BlzSetSfxX will not inline because you need another line to record the x/y (BlzSetSfx is local so there is no synced GetX/Y). Treating units as a datastructure also has some other implications, such as you can attach multiple effects to 1 unit to make missile trails (a common use case of attaching ribbons). If you relied on SetSfxX/Y you'd have to update each and every one of them, whereas with old xefx you just moved the unit. This means there are less stress on SetX/Y with unit-based xefx than moving effects.

Of course if you use lua it doesn't matter as lua engine performs better than the jassVM due to lua runtime being "closer" to the OS and consequentially closer to the processor/memory stack.
Not to sound rude, but I really don't care how jass performs. It's obsolete and only used by people who update old maps and/or refuse to learn the newer/better languages.
When I asked for source I meant benchmarks (using os.clock), not speculation why you think one system may or may not perform better than another.

Good. If I make a jass/lua library to have a SyncedGetZ, you'll find it there.
Looking forward to it ^^

I don't think so. It uses new native API (as evidenced from screenshots + UI difference), so they probably just saved their map in 1.32.
Ah, I did not read that we were talking about using the SD-only feature in the context of old maps. It's true the map I linked was saved in 1.32 editor.

This doesn't work if the map you're trying to play is not yours and "protected". Copying .w3i directly to mpq file (and/or deleting old .w3i) either corrupts the map or make it crash your computer.

If anyone knows a way to have this trick work I would be most interested, and so are many other map makers.
You could check out this. With some minor adjustments it can work the other way and 'upgrade' the .w3i to 1.32. I cannot test it myself though, since I uninstalled reforged.
 
Level 6
Joined
Jan 17, 2010
Messages
149
Not to sound rude, but I really don't care how jass performs. It's obsolete and only used by people who update old maps and/or refuse to learn the newer/better languages.
When I asked for source I meant benchmarks (using os.clock), not speculation why you think one system may or may not perform better than another.
You should know nobody cares about Jass enough to make benchmarks for the new natives. I can't be bothered to do them myself since I won't benefit from it in any capacity. I edited the message to say "Blz native" specialised Missile will be faster as it removes dependency on xefx alltogether. But that only applies to new maps with no regression risk, which by that point might as well use lua. So probably no point even discussing this further as new missiles using BlzSetFX will blow SetUnitX/Y out of the water.

There is still a sizeable portion of the wc3 community that still stuck on Jass both on battle2.net and elsewhere (small thanks for Blizzard botching 1.30, 1.31, and 1.32 patches). So the "only used by people who update old maps" is not a small only.
 
Level 18
Joined
Jan 1, 2018
Messages
728
You should know nobody cares about Jass enough to make benchmarks
That's exactly what I said. FYI, os.clock is a lua function.

"only used by people who update old maps"
only used by people who update old maps and/or refuse to learn the newer/better languages
Also, when I said "update old maps", I was mostly talking about people who play on 1.32, so yes that is a small only. But you're right, jass is only used by people who update old maps and/or refuse to learn the newer/better languages and/or refuse to play on 1.31 or higher. Hope I didn't forget anyone this time.

(small thanks for Blizzard botching 1.30, 1.31, and 1.32 patches)
I'm probably biased due to lua addition, but I don't get the hate, what was wrong with 1.31 again?
 
Level 6
Joined
Jan 17, 2010
Messages
149
I'm probably biased due to lua addition, but I don't get the hate, what was wrong with 1.31 again?

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.
 
Level 6
Joined
Jan 17, 2010
Messages
149
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.
 
Level 6
Joined
Jan 17, 2010
Messages
149
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:
Level 2
Joined
Aug 27, 2019
Messages
7
GetLocationZ was still unsafe between Windows/Mac players. It even warns you in common.j:


If you need synchronized data about the terrain height, then scan the map using one player and synchronize the data using `BlzSendSyncData`. It might take a while but it'll work. The approach you're suggesting will also work.

Also, I don't know where you got that 1,000,000 figure from. A 256x256 map has 257x257 height points. That's 66k points. You also don't -really- need full 32 bits of precision most likely, and can represent the height in your map using 16 bits. That's 128 kilobytes. Easily embeddable in Lua maps as a string which can be also easily decoded at init time.
upload_2020-3-29_15-15-32.png
Is it like this? But too much data needs to be synchronized. What should I do?
 
Level 6
Joined
Jan 17, 2010
Messages
149
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.
 
Level 2
Joined
Aug 27, 2019
Messages
7
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?
 
Level 6
Joined
Jan 17, 2010
Messages
149
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:
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:
local e
local s
if GetLocalPlayer() == Player(0) then
    s = "mymodel.mdl"
else
    s = ""
end
e = AddSpecialEffect(s,0,0)
 
Just stop. 5 star system on hive using GetLocationZ -> [vJASS] - Missile all maps using it are now at risk. I don't care who's at fault and neither should you or anyone else reading this. It is what it is.is.
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.
 
Level 6
Joined
Jan 17, 2010
Messages
149
Missile does nothing with GetLocationZ that desyncs.

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:
                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 <-
 
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.
 
Level 6
Joined
Jan 17, 2010
Messages
149
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.
 
Level 6
Joined
Jan 17, 2010
Messages
149
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.
 
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.
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:
Level 6
Joined
Jan 17, 2010
Messages
149
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)

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:
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.
View attachment 351568
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.
 
Level 6
Joined
Jan 17, 2010
Messages
149
most usecases.

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).
 
Level 6
Joined
Jan 17, 2010
Messages
149
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.

Bye. It is you who refuses to understand.

I'm telling you and everyone else who has the misfortune of shovelling through this crap that I have TESTED it and it does desync. We tested it MULTIPLE TIMES TO BE SURE. Does it desync in the most recent patch? I don't know. but it did 1-2 months ago. I adopted/created a synced GetZ that solves this problem permanently and efficiently, so this isn't an issue for me anymore, but it might be for some other people.

For those who are curious what exactly can desync in the map here is the boiled down test case:
Fire a missile (Missile.j) over this terrain segment and then walk your units around (probably to trigger a movement update event in the netcode). result was a near instant desync. This requires someone using reforged and someone using classic. This particular terrain was created with steep cliffs in WE JNGP. In reforged GetLocationZ will return (0-0.5) difference for some reason in some of the "squares regions in the grid" on the decline portion of the terrain.

upload_2020-4-5_13-39-30.png
 
This is because FlyHeight affects occlusion on steep cliffs and it was always like this since the beginning of wc3. Again, this has nothing to do with Reforged and could potentially happen without Reforged too. The only reason it now happens more frequently is because Reforged cliffs might have different occlusion height than classic cliffs.
 
Level 6
Joined
Jan 17, 2010
Messages
149
This is because FlyHeight affects occlusion on steep cliffs and it was always like this since the beginning of wc3. Again, this has nothing to do with Reforged and could potentially happen without Reforged too. The only reason it now happens more frequently is because Reforged cliffs might have different occlusion height than classic cliffs.

That is 100% correct and the entire essence of this topic.

I didn't intend to claim GetLocationZ being bugged or any such nonsense. Generally pre 1.32 it wasn't an issue as all terrain meshes rendered equally save perhaps on Mac, which made GetLocationZ effectively synced as long as no terrain deformations were present. This made all Missile coders assume GetLocationZ was safe to use, which proved to be not a future-proof assumption given what Blizzard did to make cross play possible.

In other words: This topic is 1 giant warning about a potential source why people Desync in reforged x classic mode.
 
Status
Not open for further replies.
Top