dslake / WorldDownloader

Clones a Minecraft multiplayer world from a remote server to your singleplayer folder
http://www.minecraftforum.net/topic/1444862-
62 stars 19 forks source link

[v2 beta] Crash after going though a Nether Portal #2

Closed nairol closed 11 years ago

nairol commented 12 years ago

Steps to reproduce

  1. Build Nether portal
  2. Start download
  3. Walk into the portal and wait for the teleport
  4. The game crashes because of this code in WDL.java (line 156; method onWorldLoad):
if( downloading ) // This should NEVER happen! (famous last words, lol)
    throw new RuntimeException( "World Downloader: Couldn't stop download! Check your worlds!" );

Problem

Probably has something to do with the new class WDLSaveAsync. WDL.downloading is set to false very late in the saving thread. This worked well when saving was synchronous but is a problem now because the onWorldLoad hook gets called before saving is complete.

Possible solutions

dslake commented 12 years ago

I think I have an easy fix for this. It's like your option #1. I was using the downloading flag during save so that the user would not start another download if the previous download was still saving. Still, it may take many seconds for the previous world to save so the async save is very important. It can be actively saving the overland world while the user is exploring the nether or some other dimension. Multiple async saves can be happening at the same time so if they went from dimension 1 to dimension 2 then to dimension 3, they would potentially all be saving at the same time. I'll set downloading to false but keep isSaving or whatever I called it to true. That makes it so the "Saving..." chat message will still be printed every 5 seconds. I'll add the name of the world to that message so the user knows what is being saved. Good catch and debugging, thanks.

On Tue, Sep 4, 2012 at 2:31 PM, Florian notifications@github.com wrote:

Steps to reproduce

  1. Build Nether portal
  2. Start download
  3. Walk into the portal and wait for the teleport
  4. The game crashes because of this code in WDL.java (line 156; method onWorldLoad):

if( downloading ) // This should NEVER happen! (famous last words, lol) throw new RuntimeException( "World Downloader: Couldn't stop download! Check your worlds!" );

Problem

Probably has something to do with the new class WDLSaveAsync. WDL.downloading is set to false very late in the saving thread. This worked well when saving was synchronous but is a problem now because the onWorldLoad hook gets called before saving is complete. Possible solutions

  • Move WDL.downloading = false; to the beginning of the thread or even out of the thread (???)
  • Delay the method onWorldLoad until the saving thread has finished (???)
  • Something else?

    — Reply to this email directly or view it on GitHubhttps://github.com/dslake/WorldDownloader/issues/2.

danthedad

dslake commented 12 years ago

Hmm. The actual saving of the chunks is always asynchronous in Minecraft. When you call saveChunk, it just queues it up in the ThreadedFileIOBase queue. The queue processor only tries to save one chunk every 10ms from what I can tell. If there is a thread waiting on the queue to be empty, then the delay is removed and it goes full speed.

There are a couple of reasons I added a new thread to do the saving and another thread to report on the progress of the save. First, when the user clicks "Stop Download", there is a delay as the gui screen is still displayed until stop() completes. None of the saving chat message come out until the saveEverything function (actually just queuing) is complete. The reason for the async save class is to have a thread that can block on the actual queue processing so we know for sure when it's done. Blocking on the save on the main game thread may crash the game or at least disconnect the client from the server due to response time-out. The second save reporter thread monitors the status of the WDL.isSaving flag and reports "Saving..." every 5 seconds until it's complete.

Having the WDL save be asynchronous means that swapping out the WorldClient, Player, Minecraft instance, etc just as the save thread is starting up will cause race conditions. The save thread needs to have a reference to the world and player that it's currently saving, while the player is free to move to another world.

A solution may be to start up the save thread with the data needing to be saved. Mainly, a reference to the WC, Player, and maybe some flags or overrides. It can finish up, monitor and report the progress of the save while the main WDL class either just stops or starts up with a new world in the case of moving into the nether.

I tried out some options tonight and I'm not satisfied with any of them yet. It would be nice to prevent the user from stopping and then re-starting the download while it's still trying to save. Also, if the user moves to the nether, the save reporter could let them know when it's safe to move back to the overland world.

nairol commented 12 years ago

I have only looked at this issue superficially and will also not be able to help for the next few days, sorry.


Another option would be to remove all the static from the WDL class and use one WDL object for each WorldClient that is created in a Minecraft session. That would be another big rewrite though.

johnmlang commented 11 years ago

This also occurs when entering a portal to The End. Let me know if there is any information I can provide.

Crash Report:

  Minecraft has crashed!      
  ----------------------      

Minecraft has stopped running because it encountered a problem; Unexpected error This error has been saved to /home/strider/.minecraft/1.4.2/.minecraft/crash-reports/crash-2012-10-29_12.36.13-client.txt for your convenience. Please include a copy of this file if you report this crash to anyone.

--- BEGIN ERROR REPORT 8ca17141 -------- Generated 10/29/12 12:36 PM

java.lang.RuntimeException: World Downloader: Couldn't stop download! Check your worlds! at WDL.onWorldLoad(WDL.java:157) at awz.a(WorldClient.java:151) at awr.a(NetClientHandler.java:1114) at dl.a(SourceFile:135) at bx.b(SourceFile:341) at awr.d(NetClientHandler.java:90) at awz.b(WorldClient.java:64) at net.minecraft.client.Minecraft.l(SourceFile:1282) at net.minecraft.client.Minecraft.J(SourceFile:582) at net.minecraft.client.Minecraft.run(SourceFile:534) at java.lang.Thread.run(Thread.java:722) --- END ERROR REPORT 13445570 ----------

johnmlang commented 11 years ago

When leaving The End for the Overworld, the client does not crash. Instead the download is automatically stopped and the "Chunk saving complete" message is displayed. The download must be manually resumed.

dslake commented 11 years ago

I posted BETA 6 in the forums which should fix this crash.