Pokechu22 / WorldDownloader

Makes a copy of parts of a multiplayer world for singleplayer use (EG, for backups or renders)
https://www.minecraftforum.net/forums/mapping-and-modding-java-edition/minecraft-mods/2520465-world-downloader-mod-create-backups-of-your-builds
Other
568 stars 135 forks source link

Downloading Pixelmon Entities doesn't work #232

Open Kile467 opened 2 years ago

Kile467 commented 2 years ago

Hi! Awesome work!! Congrats for all the amazing work!!

I'm currently having an issue downloading my world with Pokemon's spawned, Pokemon statues as well as different NPCs. This type of entities appear in the filter list of what MWD downloads. I have all checked, but MWD only downloads Pokemon Statues. I'm genuinly interested in quickly copy the Chatter NPCs, Mover Relearners, Nurses and all kind of NPCs Pixelmon Mod offers, but it doesn't appear in the world's singleplayer copy.

image image

Do you have any clue about why is this happening, and any workaround to make MWD copy this NPCs?

Thanks a lot!

Version

Game: Minecraft 1.12.2 Downloader: latest Launcher (if login issues): 14.2

Pokechu22 commented 2 years ago

Entity tracking is a fairly complicated feature because there isn't a good way to distinguish an entity unloading versus an entity dying/getting removed. This is solved by deciding between the two based on the distance from the player. But that also requires storing a list of all of the distances due to how the game works, which is only possible for vanilla entities. For modded entities, you'll need to enable manual track distances and set the value to the right thing. If you're not sure what the right value is and don't want to try and determine it experimentally, set it to something small (e.g. 1), as that will err on the side of saving more things.

Kile467 commented 2 years ago

Thanks for explaining me the issue with entities!! Checking player distance is a good solution.

How can I enable manual track distances and set the value? Any in game mod setting?

I guess the numeric value equalls distance in blocks. I will begin with small ones as you have suggested.

Thanks a lot for the quick response!! I'm very grateful for the awesome tec support!

Pokechu22 commented 2 years ago

The text at the top of the UI should say "Track Distance: Default"; click it and it should change to "Track Distance: User", allowing you to use the sliders. The distance is measured in blocks (though I don't think it's normal distance; if I recall correctly it's the distance along the x axis or along the z axis, whichever is larger). Note that that distance is different from the distance at which the entity stops renderering; the easiest way to find distances is to turn the "Removing entity" message in the message options.

I wrote some documentation on the subject here: https://github.com/Pokechu22/WorldDownloader/wiki/Entities-GUI - I'm not sure how up-to-date it is, since I wrote it a while ago, but it should help.

Kile467 commented 2 years ago

Wow! Sorry, I don't know why I didn't relate the feature you were telling me with the sliders, sorry!! hehe

Okay! Thanks for the documentation! After reading and testing with the distance in 1, nothing happened:

Curious is that all of that entities are from Pixelmon, and all are pasive. So I have two theories:

image

Pokechu22 commented 2 years ago

One other thing to try is to stand next to one of the NPCs you want saved, and then start and stop downloading. Entities that are loaded when you stop downloaded are always saved (without having to worry about track distances).

If they still aren't saved when doing it this way, it's possible that something with how the entities work is incompatible with the way that world downloader saves them - in which case there's no easy fix, unfortunately.

Kile467 commented 2 years ago

Yup. I tried! One thing I noticed this time is that when I press save, after downloading, Chatting NPCs disappears while saving bars are on screen. After that, Chatting NPCs reappear. That could be the reason why they are not being saved at all. They do a stream out event while saving.

Do you have any clue about why they disappear in this precise moment?

Pokechu22 commented 2 years ago

No, that's very odd. Entities in the world should continue rendering normally during the saving screen; it's using normal game rendering (for the most part; there are some complications with how the rotating camera is actually implemented) and not trying to show in particular what is being saved.

Can you clarify what you mean by a "stream out event"? As in, is there an actual animation that is performed, or are they just not visible?

Kile467 commented 2 years ago

Yeah, sure!! In game development terms, multiplayer related: Stream-in is when an NPC/entity/ped/player enters the area of influence (stream area) of another NPC/entity/ped/player and event happens in the client of the player. Stream-out is the same thing but exiting the streaming area.

As you explained above, it is not the same thing as rendering, because the entity can exist in the client but the player could not see it/render it. Stream-in and stream-out are client events thrown to the server or received by the client from the server, and the server have some handlers as well as the client.

Explanations aside, I've recorded a gif so you can see what is happening!

https://gyazo.com/271e1d9b1f9224f844cb04570e047511

After the saving stopped, and a few seconds running around, NPCs reappear and all the functionality is working as usual.

Quite strange.

Pokechu22 commented 2 years ago

Ah, those terms make sense and are a lot less ambiguous. The Minecraft Protocol documentation on wiki.vg uses "Spawn Entity" and "Destroy Entities" currently for the same purpose. For vanilla Minecraft, the server is completely responsible for choosing what entities are sent/streamed to the client and when. Possibly pixelmon does it differently, but it seems unlikely that they'd reimplement this.

WDL saves entities when the stream-out occurs, so I would expect to see a "removing entity" message in chat if that happened (though having it happen during saving is a bit of an edge case, and I'm not 100% sure WDL still listens for that during saving).

It's possible that pixelmon has entities that can't be saved properly with a client world; it seemed like it disappears when the chunk it is in was saved, but that doesn't explain why it reappears later.

Kile467 commented 2 years ago

Yeah! Those terms are used every day in gamedev. Minecraft have changed the naming of architecture's concepts, but they are all the same because videogames hehe.

WDL saves entities when the stream-out occurs, so I would expect to see a "removing entity" message in chat if that happened (though having it happen during saving is a bit of an edge case, and I'm not 100% sure WDL still listens for that during saving). It's possible that pixelmon has entities that can't be saved properly with a client world; it seemed like it disappears when the chunk it is in was saved, but that doesn't explain why it reappears later.

Pixelmon should work the same as normal MC entities with streaming :(

You can create the same entities in a SP Player World. The only thing that could be happening is what you are saying in the last sentence: WDL can't download the entity data struc.

I would love to know why it reappears after saving. How the "Start download" and "Stop download" processes work exactly?

Pokechu22 commented 2 years ago

You can create the same entities in a SP Player World.

Even in singleplayer, there is both a server and a client, with the server world handling ticking and physics and the client handling rendering and interactions (more or less); the same packets are used to exchange data between the two (though no actual network connection is used). Saving normally happens with the server world, but WDL has to use the client world instead. The server also doesn't always send all of the data to the client, but generally any entity will have default values that are used instead.

How the "Start download" and "Stop download" processes work exactly?

Start download doesn't do anything particularly interesting; it mostly just prompts for multiworld configuration and then tells WDL to start listening for various events. Once downloading is started, any entity removal packet results in that entity being stored for later saving when its chunk is unloaded (if the distance check passes), and any chunk unload results in that chunk being saved (including entities that were stored for later). There is also inventory-related logic that isn't relevant here.

When the stop download button is clicked, all currently loaded chunks are saved, including entities that were stored for later use. The highest level of saving logic is manually implemented (WDLChunkLoader.java) based on vanilla logic; it was duplicated so that stored entities don't need to be put into the actual world and instead the entity list when saving can be manually handled. Saving individual entities works by calling their NBT writing functions and is not manually implemented; it depends on the entity being able to properly save itself with the data the server sent.

Entities can theoretically do whatever they want in the save function, but generally it's just serializing data. There isn't a normal reason why they'd disappear from that.


Oh, I do have one idea actually: WDL has some legacy functionality to move entities back to the last position the server sent for them to work around various old game bugs where the entity would move on the client world when it shouldn't (see e.g. https://i.imgur.com/3QQchZL.gifv - and note that the boat jumping back to its previous position is the server updating its position, not just the video looping). But if entities use special position logic, this can result in them being at the wrong position (usually 0, 0, 0); in vanilla this applies to hanging entities such as paintings (and the entity realignment logic is disabled for those entities). You can turn this off by going into the extension options (I think this is under "about world downloader") and disabling "Entity realigner".

Kile467 commented 2 years ago

Sorry for the late response. I had a busy weekend I'm afraid!

Thanks a lot for the client-server packet and Star/Stop Download functionality explanation!! I appreciate you took your time ^^

Knowing how entites are stored, and you replicate AI calling vanilla NBT gives me some clues about why this particular Pixelmon Entities disappear and are not saved properly. Chatting NPCs, Shopkeepers and Nurses/Doctors take some information from jsons stored in the MC folder. This jsons expands the original functionality of Pixelmon, like custom items in stores, more dialogue configurations, custom quests...

https://pixelmonmod.com/wiki/NPC_JSONs#Chatting_NPCs

If you pull the data assuming the NPC is vanilla (because this mod has been crafted for vanilla, ofc) and WDL don't have access to MC Server folder, these entities will be incomplete in the saving process. WDL detects this issue and decides to not save them avoiding corrupted data. Have to say you crafted the saving process with coding quality!

After all of this I'm not quite sure if there is a quick workaround for this, because part of the data needed to store this entities is in the server itself. Another workaround is to store this entities with the default config of Pixelmon, but that requires a mod update and it's not worth it at all, to be honest!

I will try your last suggestion and I will let you know if it works!!

Thanks a lot for your time, explanations and patience!!


Edit: Okay! I've tested disabling the "Entity realigner" option, and that doesn't work at all. I'm pretty sure what I told you before is the main issue: Taking data from a json from the MC Server Folder causes WDL to not download it at all to prevent potential issues.

At this point I don't know if there is some kind of workaround. Anything come up to your mind? Thanks!!