-
Notifications
You must be signed in to change notification settings - Fork 4
Issues with old versions
Alpha 1.1.1 called the LWJGL method Display.setDisplayConfiguration(1.0F, 0.0F, 0.0F)
repeatedly, which wasn't a good idea.
Solution:
RetroWrapper no-ops calls to Display.setDisplayConfiguration(1.0F, 0.0F, 0.0F)
. Alpha 1.1.2 should also be identical to 1.1.1, minus the call to Display.setDisplayConfiguration(1.0F, 0.0F, 0.0F)
.
For some strange reason, ARM-based macOS uses BGR colours in windowed mode and RGB colours in fullscreen mode.
Solution:
The easiest solution is to play in fullscreen, which is possible when wrapping instances with the "update libraries" option. I'd also recommend using the "patch LWJGL natives" option.
RetroWrapper has a set of experimental patches which modify various functions to use BGR colours in windowed mode and RGB colours in fullscreen. Enable these with -Dretrowrapper.enableExperimentalPatches=true
. Use -Dretrowrapper.enableExperimentalPatches=true -Dretrowrapper.forceM1PatchToValue=ForceEnable
to force the patches to be used.
Over time, the way that connecting to servers has changed, and a number of login endpoints have been changed or taken offline. See Pokechu22's comment for a full explanation of what endpoints are offline.
Solution:
Per WEB-1429, it's possible that this will be fixed by Mojang in the future, so waiting a couple of years may fix this.
Alternatively, the easiest way to patch this is to simply re-direct old endpoints to the Minecraft.net equivalents.
Using the current API is a more robust solution if the older Minecraft.net endpoints stop working.
RetroWrapper tries to use the current API, and uses the Minecraft.net endpoints if this fails.
Some versions of Minecraft call the LWJGL method setNativeCursor
to show / hide the cursor. However, this throws an IllegalStateException
on macOS, which Minecraft doesn't handle.
Solution:
RetroWrapper patches these calls to handle this exception.
There are at least two issues contributing to this: the use of minecraftApplet, and a LWJGL 2 bug. BetaCraft and MCPHackers/LaunchWrapper have a "deAWT" patch, which fixes the first issue, but the LWJGL 2 bug still prevents resizing from working. Minecraft 1.6 and onwards aren't affected by the first issue, because they don't use minecraftApplet, but they're still affected by the second issue.
The LWJGL 2 bug occurs on every version that uses it (pre 1.13). It always occurs on ARM-based macOS, but it's a known issue that could affect x86_64 versions of macOS. The bug is most likely caused by a race condition when resizing the window, possibly related to OpenGL contexts or main thread dispatch issues.
Solution:
Don't resize the window ¯\_(ツ)_/¯
Cross platform input is hard and nobody understands.
Solution:
RetroWrapper patches old methods of mouse input and re-implements it using LWJGL methods.
The old online save servers are long gone. Endpoints include:
-
http://(applet base url)/listmaps.jsp?user=(username)
- List all maps from 0 - 4 for the given user, including empty ones. Note that if this doesn't respond, some old versions of Minecraft also won't save and load locally as well. -
http://(applet base url)/level/load.html?id=(level id)&user=(username)
- Load the given level ID (0 - 4). -
http://(applet base url)/level/save.html
- Save the given level to the given ID.
The applet base URL was www.minecraft.net
when launched on minecraft.net.
Solution:
If a full solution is not needed, listmaps.jsp
can be mocked by simply returning "-;-;-;-;-;" to indicate five empty save slots. This at least fixes the issues with local saving on some old versions of Minecraft.
For a full solution, you'll want to handle loading and saving. RetroWrapper implements the method below.
Send: 5 levels, with the format of level name, or "-" to indicate no level for this ID, plus ";" to indicate the end of the name.
Example:
"TestLevel;OtherLevel;-;-;-;"
Receive:
- UTF: Username
- UTF: Auth token
- UTF: Level name
- Byte: Level ID (0 - 4)
- Int: Level length
- Byte[]: Level data, of length level length
Save the level to a file corresponding to the level ID, as well as the level name.
Send:
- "ok\n" for a successful save, anything else with a newline if not
Get the level ID from the URL parameters.
Send:
- "ok" for a successful load, anything else if not
- If successful, the level data for the given level ID
More information about the Classic level format can be found here.
Launching Minecraft from an Applet (calling init()
on the Applet) will set a field indicating that it's been launched in an Applet. Among other things, this field can determine if the quit button is shown.
Solution:
ASM / reflection, or not launching Minecraft from an Applet. Currently, after finding the Minecraft field, RetroWrapper finds the first public boolean field of the most super class of the Minecraft class. This is the "launched from an Applet" field. RetroWrapper sets it to false on the Minecraft object.
This is because the URLs used to download skins and capes have changed, as well as the format of the requests.
Previous skin URLs include:
http://www.minecraft.net/skin/(username).png
http://s3.amazonaws.com/MinecraftSkins/(username).png
http://skins.minecraft.net/MinecraftSkins/(username).png
Previous cape URLs include:
-
http://www.minecraft.net/cloak/get.jsp?user=(username)
, which would re-direct tohttp://www.minecraft.net/cloak/(a cape).png
http://s3.amazonaws.com/MinecraftCloaks/(username).png
http://skins.minecraft.net/MinecraftCloaks/(username).png
It's unlikely these endpoints will be restored in the future.
Solution:
Skin and cape URLs must be re-directed, proxied, or replaced through other means. Modern skin download methods using the Mojang API require a UUID as well as parsing JSON responses and decoding base 64.
RetroWrapper's server emulator handles skin and cape requests using the Mojang API. It gets the UUID of the player, and requests the skin URL, downloads the skin and caches it on disk and in memory, and sends the downloaded skin to the client. Skins and capes can then be retrieved offline in the future.
Minecraft skin formats have changed over time. Most recently, skins were expanded from 32×64 to 64×64 to add new layers, and the slim arms ("Alex") format was added. When requesting the skin / cape URL with the Mojang API, the response also includes if the skin is a slim arms skin or not. Various old versions of Minecraft also have slight differences in how skins are parsed (TODO research this).
Solution:
Skins can be overlayed, stretched, and cropped to the correct size on older versions which do not support slim arms and 64×64 skins. Currently, RetroWrapper only crops skins, but I plan to add overlay and stretching support in the future.
The URLs used to host resource files have changed over time, as well as the format of the resource index.
Previous resource URLs include:
-
http://www.minecraft.net/resources/
(with a text-based index format) -
http://s3.amazonaws.com/MinecraftResources/
(with a XML based index format)
Solution:
The vanilla launcher solves this by just downloading files ahead of time, which generally works. The BetaCraft proxy is also a great solution, as it has per-version correct proxies and is generally easy to use.
If you want to make your own solution, you can parse the assetIndex for the client .json file, or use a fixed / custom index of your choosing. When not using per-version sounds, RetroWrapper uses a mix of legacy.json for the http://www.minecraft.net/resources/
endpoint, and pre-1.6.json for the http://s3.amazonaws.com/MinecraftResources/
endpoint. This page describes the index format, and how to download a given asset from the Mojang servers.
When http://www.minecraft.net/resources/
is requested (classic / indev), you should return a new line separated list of all files in the form (resource name),(resource size),(Unix timestamp)
.
Example:
sound/step/stone3.ogg,6627,1246117587000
sound/step/stone1.ogg,6695,1246117587000
...
music/calm2.ogg,1961732,1245702004000
This list should end with a new line.
Of note that for these versions is that Mojang renamed "sound/random/wood click.ogg" in their current index to "sound/random/wood_click.ogg". This can be handled by changing the name of this file when parsing the asset index. I also filter the list of files to only include files which were available before the endpoint was changed, to possibly save on network requests and present a more authentic experience.
When http://s3.amazonaws.com/MinecraftResources/
is requested, you should return a XML file corresponding to the ListObjects format.
Example:
<?xml version="1.0" encoding="UTF-8"?>
<ListBucketResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<Name>MinecraftResources</Name>
<Prefix></Prefix>
<Marker></Marker>
<MaxKeys>1000</MaxKeys>
<IsTruncated>false</IsTruncated>
<Contents>
<Key>music/</Key>
<LastModified>2010-09-23T12:07:11.000Z</LastModified>
<ETag>"d41d8cd98f00b204e9800998ecf8427e"</ETag>
<Size>0</Size>
<StorageClass>STANDARD</StorageClass>
</Contents>
<Contents>
<Key>music/calm1.ogg</Key>
<LastModified>2010-10-30T19:51:26.000Z</LastModified>
<ETag>"3c5b792652b43e9876b7e7b19c0b376b"</ETag>
<Size>2530812</Size>
<StorageClass>STANDARD</StorageClass>
</Contents>
...
<Contents>
<Key>streaming/where are we now.mus</Key>
<LastModified>2010-09-23T12:07:35.000Z</LastModified>
<ETag>"5390ff05f81dec44a072ad137e9c1630"</ETag>
<Size>1845255</Size>
<StorageClass>STANDARD</StorageClass>
</Contents>
</ListBucketResult>
Many of these fields are not used. Each file, folder, and subfolder should at least have a contents entry with a key and size.
Finally, of note for both when http://www.minecraft.net/resources/
and http://s3.amazonaws.com/MinecraftResources/
are requested, you should probably skip all top-level files (any files not in a folder).
RetroWrapper caches all index .json files and asset files downloaded to folders corresponding to the index. Additionally, RetroWrapper checks the vanilla launcher's index cache (under assets/indexes) and asset cache (under assets/objects) for already downloaded files as well as various fallback locations (the resources folder, various locations relative to the launch directory if this is not the vanilla launcher etc) to save on network requests and allow better offline play.
Unfortunately, Mojang only has one current sound index for all versions older than 1.6, meaning that each of those versions share the same sounds. Additionally, Mojang doesn't host older versions of sound files, such as the old door sound.
Solution:
RetroWrapper currently falls back on BetaCraft to get a sound index corresponding to the detected Minecraft version, and downloads / caches the few files not hosted by Mojang from BetaCraft. I plan to implement a custom solution in the future.
This is a vanilla quirk, due to the depth buffer not having enough bits.
Solution:
RetroWrapper patches calls to Display.create()
to be Display.create(new PixelFormat().withDepthBits(24))
instead.
- Document Applet parameters
- Document Classic server connections
- Document working directory fix
- Document other URLs