CleverRaven / Cataclysm-DDA

Cataclysm - Dark Days Ahead. A turn-based survival game set in a post-apocalyptic world.
http://cataclysmdda.org
Other
10.61k stars 4.17k forks source link

Segfault related to modded gun. (Possible pocket assignment problem during saving/loading) #41064

Closed Menschheit closed 4 years ago

Menschheit commented 4 years ago

Describe the bug

The rifle (shown as "HK417 A2+1") is always generated with an adjustable stock , which disappears after saving and loading (and we will have a "HK417 A2" without "+1" after that). This may cause segmentation fault error if the player has reloaded the original "HK417 A2+1" with a magazine before "Save and Quit".

Steps To Reproduce

  1. Generate(or loot) a HK417 A2 +1.
  2. Reload "HK417 A2 +1" with an appropriate magazine. (Skip this step if there is one in it already)
  3. Save and Quit. Then load the save file.
  4. You will see that the rifle becomes a "Hk417 A2" without any mods. Now unload the gun.
  5. The game crashes any time you examine the gun (iventory, examine and so on) without a magazine in it.

Expected behavior

The adjustable stock should not disappear, game should not crash.

Versions and configuration

Additional context

If the "HK417 A2 +1" was kept unloaded before it becomes "HK417 A2" after saving and loading, no crash will occur.

crash.log: crash.log

debug.log: debug.log

save file(the nearest gun above can cause crash): TEST WORLD.zip

CptFail92 commented 4 years ago

I get a crash if I (U)nload the RM51 or SIG 552 and then (a)ctivate on this save. It may be related. crash.log

Arredondo.zip

MikuMiddo commented 4 years ago

In fact,any modified guns ,bow,crossbow or any other modified weapon will make the game Segfault crash after you restart the game then [U]nload them.

Menschheit commented 4 years ago

In fact,any modified guns ,bow,crossbow or any other modified weapon will make the game Segfault crash after you restart the game then [U]nload them.

True, all gun mods are lost across save, better to stick to my fire axe for now.

Menschheit commented 4 years ago

Additional Info:

  1. Guns of the same type but with different mods can stack in iventory.

  2. Can't find anything about attached gun mods in the save file. In older version, the attached mods are listed with a "contents" tag after the gun infomation.

  3. Get the massage "error: tried to put an item into a pocket that can't fit into it while loading." after loading saves. 2

Menschheit commented 4 years ago

Additional Info:

  1. The gunmods are written into save only if there is a magazine in the gun. Otherwise all information about mods are lost.
  2. Assume that the gun is always loaded with magazine and we save the game. In the saved file the magazine is assigned with "pocket_type": 2 ; the gun mods are assigned with "pocket_type": 3. Now load the save, and save again immediately. Check the saved file, gunmods are now assigned with "pocket_type": 4 .

So I think there is sth, wrong with pocket assignment during saving/loading, hope this get fixed soon.

meladath commented 4 years ago

Crash occurs here as contents are null image

Whilst trying to get the item's name here inside item::display_name image

Will try to investigate further.

Menschheit commented 4 years ago

Crash occurs here as contents are null image

Whilst trying to get the item's name here inside item::display_name image

Will try to investigate further.

This PR https://github.com/CleverRaven/Cataclysm-DDA/pull/41420 only fixes the crash, didn't fix gunmod disappearing.

Actually there are two problems:

  1. The contents are "combined" to pockets after loading, but since guns dont have a "pocket_type": "MOD" defined in .json so there are some chaos on pocket asignment. I don't know how exactly it is processed (I have no coding experience and the source codes lack comments) but it seems that adding a "pocket_type": "MOD" in json file (for all guns) may solved the problem.

  2. In savegame_json.cpp a The function item_contents::empty() just ignores mods. So if there is no magazine or magazine_well in a gun, the gun will be considered as "empty" hence the contents will not be serialized. We need another funtion here to check if an item is really "empty".