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

129ifier Automated Script

Is it a good idea?

  • Yes

    Votes: 7 87.5%
  • No

    Votes: 1 12.5%

  • Total voters
    8
  • Poll closed .
Status
Not open for further replies.
I have this idea that you could write a program where you choose a map (even if it is optimized and protected) and then it ports the map to 1.29, fixing any compatibility issues automatically.

What is any reason not to do this? I did not make it yet, but I believe it could be done. DrSuperGood created a Java lib for BLPs that is supposed to be super good so we should be able to tell which BLPs are "corrupted" as per the 1.29 definition. Also, for maps from before Patch 1.24, there is a forward port for any return bug system that can be done in an automated way which I used to produce a running version of the TToR mod (which I last had working on 1.21) that worked on 1.28.

We know the scope of what must be done to port a map into the modern environment. Why don't we have this automatic updater tool? Any reason it couldn't be done (in case I try to write it later)?

Then we could begin to unify the existing community and get people stuck on 1.26 or 1.28 to have their maps run on 1.29.

Obviously memory hack would not be supported because you can't automatically move that stuff to 1.29 because it's a bad idea that shouldn't be supported and it's actually bad for me to mention it here as though it was ever a legitimate development decision made by any map developer to use such a thing. But last night I popped open old RPG maps made for Patch 1.21 and before, and played them in widescreen on 1.29, and all of these old maps worked flawlessly. The only places where little API obscurities have broken recent maps is when people tried to do illogical but functional operations -- such as BLPs with glitched mipmaps for smaller filesize and JASS stuff with the return bug, which was removed in 1.22/1.23 under the erroneous assumption that removing it would fix i2c. Hashtables were added to try to give maps the same general API behavior as the return bug, but pre-122 return bug maps all died. Removing the return bug didn't fix i2c, though, and so it was later in 1.27/1.28 where i2c memory hacking was legitimately removed by disallowing JASS bytecode to assign a value to the pointer of an array variable.

These updates have created little bizarre schizms in the community of people who just want to play the game and get things done. Yet, no update was unknown, and no update legitimately stopped previous legitimate in-game behavior from being available. And so, logically, all content authors have created should be playable on the unified modern Warcraft III.

Edit: This application should also include a UITile05 and UITile06 generator, operating to the best of it's ability
 
Last edited:
Level 13
Joined
Oct 18, 2013
Messages
690
actboy would probably dispute whether memory hacking was "legitimately removed" in 1.28 on account of him running a LUA engine through war3 on that patch ( ͡° ͜ʖ ͡°)
 
For as long as Blizzard is releasing patches again, exploiting them to break the system in odd implementation dependent ways that will change and stop working in subsequent patches is not something I want to be involved with. Whatever it is I might wish to accomplish with this game engine, I will always have an easier time of it by bugging Blizzard themselves than by caring about the madness of something like an unintended lua engine running in the game client through exploitation.
I should not even have mentioned such a thing exists.

But, on topic, I noticed that I received rep from you saying you think 129ifier is a good idea. I appreciate the feedback.
 
Level 6
Joined
May 1, 2012
Messages
95
actboy would probably dispute whether memory hacking was "legitimately removed" in 1.28 on account of him running a LUA engine through war3 on that patch ( ͡° ͜ʖ ͡°)
I need to point out that I have a patch on the lua engine, but it does not use any memory hacks. It will not do anything to inject itself into war3. The usual scenario where people use the lua engine is that their war3 has already patched this patch.

However, some people use the memory hack to inject patches into war3 on the map, but this has nothing to do with me. I personally do not recommend anyone to use the memory hack. 1.29 disabling the memory hack is too late, it should appear at 1.28, and even blz should provide an earlier war3 fix patch.
 
Level 6
Joined
Aug 28, 2015
Messages
213
I think this program would be really usefull.
One idea is coming up as I read this, could it be possible to give it always the newest update informations and this will update the maps towards the information you feed this program.
I never really bothered with cracking open the files so I don't know what it takes to do this.
From my idea how it works, it would be awsome you can dynamicly feed the patch 1.29 libraries to the program and it updates all maps to this patch and when blizzard push update 1.3 you just extrude the new libraries and feed the program with them.
 

~El

Level 17
Joined
Jun 13, 2016
Messages
551
I need to point out that I have a patch on the lua engine, but it does not use any memory hacks. It will not do anything to inject itself into war3. The usual scenario where people use the lua engine is that their war3 has already patched this patch.

However, some people use the memory hack to inject patches into war3 on the map, but this has nothing to do with me. I personally do not recommend anyone to use the memory hack. 1.29 disabling the memory hack is too late, it should appear at 1.28, and even blz should provide an earlier war3 fix patch.

Hey, is your injectable Lua engine public? I remember seeing a Lua engine somewhere else, but it was only supported on version 1.27 IIRC, and then the author disappeared. I would really appreciate if you could share it with the world!
 
Level 6
Joined
May 1, 2012
Messages
95
Hey, is your injectable Lua engine public? I remember seeing a Lua engine somewhere else, but it was only supported on version 1.27 IIRC, and then the author disappeared. I would really appreciate if you could share it with the world!

The lua engine is included in YDWE, which currently has no separate version, although you can easily extract it from YDWE. Just like someone put it on the map and use memory hack to inject war3.

This is YDWE's repo
actboy168/YDWE

This is a thread a long time ago
A Lua Engine for Warcraft 3

I don't know much about the habits of English players and English map authors. This may be the biggest reason why I didn't share my work.
 
I think it'd be an amazing idea. Definitely very challenging though.

One issue you might run into is protected maps. More than half of the compatibility update requests I've gotten were for protected maps, and it adds some complications to the coding process (a lot of mpq libraries assume there is a listfile. StormLib and a few others will work fine without one, but they cannot edit the MPQ unless you generate the listfile, so you'll have to write a namebreaker/name-searcher [which isn't too bad, just is a little annoying]).

The other annoying thing is that it is hard to completely fix the return bug. Finding the problem-lines is pretty easy, pjass will report errors for the lines that have bad returns:
lep/pjass
But fixing it isn't always straightforward. There were at least 3 different major libraries that used the return bug (Vexorian's Caster System, Vexorian's Table, KaTTaNa's Local Handle Vars), and all three of them had a generic "AttachObject"/"SetHandleHandle" function:
JASS:
function AttachObject takes handle h, string label, handle x returns nothing
    local string k=I2S(CS_H2I(h))
    if(x==null)then
        call FlushStoredInteger(udg_cscache,k,label)
    else
        call StoreInteger(udg_cscache,k,label,CS_H2I(x))
    endif
endfunction

There is a way to fix that, but it is a little tricky. If you see someone use "AttachObject(...)" where "x" is a timer, you'll replace it with "AttachTimer(...)". That is easy to fix by hand, but a lot trickier to do in code since you'll have to build some AST, and in some cases, infer the type that a person is trying to use (e.g. someone uses a handle variable instead of a more specific type).

I would probably break it up into smaller pieces at first:
  • First, add 1.29 fixes and warnings
  • Just report 1.24 issues at first. If you have time after that, write some rules to fix them. It is okay if you don't handle extreme cases like the one above imo. Just replacing H2I() alone will probably fix a lot of broken maps.
 

Kyrbi0

Arena Moderator
Level 44
Joined
Jul 29, 2008
Messages
9,487
Great idea, and send like it would be of worth to the community.

As a sidenote, I love this sentiment:
Retera said:
These updates have created little bizarre schizms in the community of people who just want to play the game and get things done. Yet, no update was unknown, and no update legitimately stopped previous legitimate in-game behavior from being available. And so, logically, all content authors have created should be playable on the unified modern Warcraft III.
It's the way I've always done things. Feels goodman.jpg : )
 
@actboy168 fixing return bug is easier than you think. There's a bug where a local and global var with same name form a C Union that leandrotp described when he reported the new memory exploits to Blizzard Entertainment. They understood the fix was to stop arbitrary memory access via JASS array assignment, so this time Blizzard did not fix the return bug and instead fixed the JASS bytecode to disallow "set" keyword being used an array variable's internal memory pointer. So, they left in the return bug. You can take any return bug function and write it with 30 lines of code and an extra global for each variable type.

Edit: as such, all maps should be playable in 1.29 or else *somebody is not doing their job*!!!

Edit: and this fix can be done in an automated fashion
 
Last edited:
@actboy168 fixing return bug is easier than you think. There's a bug where a local and global var with same name form a C Union that leandrotp described when he reported the new memory exploits to Blizzard Entertainment. They understood the fix was to stop arbitrary memory access via JASS array assignment, so this time Blizzard did not fix the return bug and instead fixed the JASS bytecode to disallow "set" keyword being used an array variable's internal memory pointer. So, they left in the return bug. You can take any return bug function and write it with 30 lines of code and an extra global for each variable type.

Edit: as such, all maps should be playable in 1.29 or else *somebody is not doing their job*!!!

Edit: and this fix can be done in an automated fashion

The return bug no longer works on patch 1.29.0.

I think it'd be an amazing idea. Definitely very challenging though.

One issue you might run into is protected maps. More than half of the compatibility update requests I've gotten were for protected maps, and it adds some complications to the coding process (a lot of mpq libraries assume there is a listfile. StormLib and a few others will work fine without one, but they cannot edit the MPQ unless you generate the listfile, so you'll have to write a namebreaker/name-searcher [which isn't too bad, just is a little annoying]).

Ladik's MPQ editor contains a deep scanning function and it works very well.

The other annoying thing is that it is hard to completely fix the return bug. Finding the problem-lines is pretty easy, pjass will report errors for the lines that have bad returns:
lep/pjass
But fixing it isn't always straightforward. There were at least 3 different major libraries that used the return bug (Vexorian's Caster System, Vexorian's Table, KaTTaNa's Local Handle Vars), and all three of them had a generic "AttachObject"/"SetHandleHandle" function

I have fixed this in multiple maps by doing something like this:

JASS:
function H2I takes handle h returns integer
    return GetHandleId(h)
endfunction

function FlushHandleLocals takes handle h returns nothing
    call FlushStoredMission(udg_gc_handlevars, I2S(H2I(h)) )
endfunction

function SetHandleInteger takes handle h, string name, integer i returns nothing
    call StoreInteger(udg_gc_handlevars, I2S(H2I(h)), name, i)
endfunction

function GetHandleInteger takes handle h, string name returns integer
    return GetStoredInteger(udg_gc_handlevars, I2S(H2I(h)),name)
endfunction

function SetHandleReal takes handle h, string name, real r returns nothing
    call StoreReal(udg_gc_handlevars, I2S(H2I(h)), name, r)
endfunction

function GetHandleReal takes handle h, string name returns real
    return GetStoredReal(udg_gc_handlevars, I2S(H2I(h)),name)
endfunction

function SetHandleHandle takes handle h, string name, handle value returns nothing
    call StoreInteger(udg_gc_handlevars, I2S(H2I(h)), name, H2I(value))
endfunction

function GetHandleUnit takes handle h, string name returns unit
    call SaveFogStateHandle(udg_HT_Typecast, 0, 0, ConvertFogState(GetStoredInteger(udg_gc_handlevars, I2S(H2I(h)),name)))
    return LoadUnitHandle(udg_HT_Typecast, 0, 0)
endfunction

function SetHandleBoolean takes handle h, string name, boolean b returns nothing
    call StoreBoolean(udg_gc_handlevars, I2S(H2I(h)), name, b)
endfunction

function GetHandleBoolean takes handle h, string name returns boolean
    return GetStoredBoolean(udg_gc_handlevars, I2S(H2I(h)),name)
endfunction

function SetHandleString takes handle h, string name, string s returns nothing
    call StoreString(udg_gc_handlevars, I2S(H2I(h)), name, s)
endfunction

function GetHandleString takes handle h, string name returns string
    return GetStoredString(udg_gc_handlevars, I2S(H2I(h)),name)
endfunction

function GetHandleForce takes handle h, string name returns force
    call SaveFogStateHandle(udg_HT_Typecast, 0, 0, ConvertFogState(GetStoredInteger(udg_gc_handlevars, I2S(H2I(h)),name)))
    return LoadForceHandle(udg_HT_Typecast, 0, 0)
endfunction

function GetHandleWeatherEffect takes handle h, string name returns weathereffect
    return null
endfunction

function GetHandleLocation takes handle h, string name returns location
    call SaveFogStateHandle(udg_HT_Typecast, 0, 0, ConvertFogState(GetStoredInteger(udg_gc_handlevars, I2S(H2I(h)),name)))
    return LoadLocationHandle(udg_HT_Typecast, 0, 0)
endfunction

function GetHandlePlayer takes handle h, string name returns player
    call SaveFogStateHandle(udg_HT_Typecast, 0, 0, ConvertFogState(GetStoredInteger(udg_gc_handlevars, I2S(H2I(h)),name)))
    return LoadPlayerHandle(udg_HT_Typecast, 0, 0)
endfunction

function GetHandleTimer takes handle h, string name returns timer
    call SaveFogStateHandle(udg_HT_Typecast, 0, 0, ConvertFogState(GetStoredInteger(udg_gc_handlevars, I2S(H2I(h)),name)))
    return LoadTimerHandle(udg_HT_Typecast, 0, 0)
endfunction

function GetHandleTriggerAction takes handle h, string name returns triggeraction
    call SaveFogStateHandle(udg_HT_Typecast, 0, 0, ConvertFogState(GetStoredInteger(udg_gc_handlevars, I2S(H2I(h)),name)))
    return LoadTriggerActionHandle(udg_HT_Typecast, 0, 0)
endfunction
 
I have fixed this in multiple maps by doing something like this:

you're right. and lmao that reminds me I made a shitty way to write GetHandleHandle as well, if you don't care for performance:
JASS:
globals
    unit gc_handle_unit = null
    timer gc_handle_timer = null
endglobals

function GetHandleHandle takes handle h, string name returns handle

    // check if unit 
    set gc_handle_unit = GetHandleUnit(h, name)
    if gc_handle_unit != null then
         return gc_handle_unit
    endif

    // check if timer
    set gc_handle_timer = GetHandleTimer(h, name)
    if gc_handle_timer != null then
        return gc_handle_timer
    endif

    // etc. lol

    return null

endfunction

iirc, it was something like that. JASS dynamic type checking at its finest! So it shouldn't be too bad to automate at all.
 
Level 13
Joined
Nov 7, 2014
Messages
571
I felt a great disturbance in the Force, as if millions of voices suddenly cried out in terror and were suddenly silenced. I fear something terrible has happened.

Noooo (in a darth-vadery kind of voice) oooouuuu...

Now Blizzard's "hidden" Set|GetTriggerUserData cannot be used! Oh well...

JASS:
library libtriggeruserdata
globals
    integer libtud_integer // not used, needed to fool jasshelper
    integer l__libtud_integer
    boolean libtud_boolean
    boolean l__libtud_boolean
endglobals

private function set_integer takes integer i returns nothing
    set l__libtud_integer = i
    return // prevent jasshelper from inlining this function
endfunction

private function set_boolean takes boolean b returns nothing
    set l__libtud_boolean = b
    return
endfunction

function libtud_enable_boolean_integer_typecasting takes nothing returns nothing
    local boolean libtud_integer
    local integer libtud_boolean
endfunction

//# +nosemanticerror
private function cast_int_to_bool takes integer i returns boolean
    call set_integer(i)
    return l__libtud_integer
endfunction

//# +nosemanticerror
private function cast_bool_to_int takes boolean b returns integer
    call set_boolean(b)
    return l__libtud_boolean
endfunction

function SetTriggerUserData takes trigger t, integer x returns nothing
    call TriggerWaitOnSleeps(t, cast_int_to_bool(x))
endfunction

function GetTriggerUserData takes trigger t returns integer
    return cast_bool_to_int(IsTriggerWaitOnSleeps(t))
endfunction

endlibrary
 
There were functions you could write with typecasting that you couldn't write with hashtables. Consider down casting. I can set a local handle type variable equal to a unit, but can't set a local unit variable to a handle. But, with the return bug, you could, and more importantly people did. So there are gazillions of ancient maps and mods that can never run on 1.29 without a full redesign (which will never happen).
 

csh

csh

Level 2
Joined
May 27, 2017
Messages
19
@actboy168 fixing return bug is easier than you think. There's a bug where a local and global var with same name form a C Union that leandrotp described when he reported the new memory exploits to Blizzard Entertainment. They understood the fix was to stop arbitrary memory access via JASS array assignment, so this time Blizzard did not fix the return bug and instead fixed the JASS bytecode to disallow "set" keyword being used an array variable's internal memory pointer. So, they left in the return bug. You can take any return bug function and write it with 30 lines of code and an extra global for each variable type.

Edit: as such, all maps should be playable in 1.29 or else *somebody is not doing their job*!!!

Edit: and this fix can be done in an automated fashion

You dont know the truth, there is another way to writing memory with return bug that leandrotp didnt report to blizzard, and memory hack system was still working on patch 1.28, so blizzard fixed the return bug on 1.29 finally.
 
That seemed to be what TriggerHappy was saying. That's why I quoted Obi Wan's little speech when he felt the Death Star destroy the planet Alderaan

What is this, an off-Topic crossover episode?

Pleasantries aside, this would greatly benefit those who would be drawn to mapmaking all over again, those who had abandoned their works long ago.
 
Level 13
Joined
Oct 18, 2013
Messages
690
Draco's dota isn't doable on 1.29, maybe someday though! any return bug / non memory exploit maps should be 100% fixable though.
 
Level 7
Joined
Jun 5, 2018
Messages
180
This sounds very interesting and useful! This technique may rescue the maps in which the memory hacks and jAPIs have been used for patch 1.29.
Perhaps some built-in and patch methods may be used for this purpose.
 
Last edited:
No, no the idea is ruined. It would be useful if we could all have a button in the editor to generate a new melee map each time we clicked it. But we don't, and we're not going to.
On Page 1 I was told that the return bug's typecasting cousin that would have allowed general case forward translation of maps was removed in 1.29. I created this thread with knowledge based on 1.28. It won't work.
 
Status
Not open for further replies.
Top