Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor!: give items identity #2250

Merged
merged 217 commits into from
Nov 4, 2023
Merged
Show file tree
Hide file tree
Changes from 127 commits
Commits
Show all changes
217 commits
Select commit Hold shift + click to select a range
a12b47e
Temp commit, now with compiling
joveeater Dec 3, 2022
ad0ef91
More refactoring
joveeater Feb 23, 2023
454ca13
vehicles fix
joveeater Mar 10, 2023
24b3ddd
More bugfixes and the start of the test suite
joveeater Mar 20, 2023
16e53ef
Merge branch 'upload' into spring-refactor
joveeater Mar 29, 2023
2380410
Merge branch 'upload' into spring-refactor
joveeater Mar 29, 2023
944cc0f
More bugfixes
joveeater Mar 30, 2023
a2b39d7
More bugfixes
joveeater Mar 30, 2023
d60311c
Beginning of better types
joveeater Apr 4, 2023
6b70aa5
More new stuff, no compiling
joveeater Apr 7, 2023
7510577
More moving to smart pointers
joveeater Apr 10, 2023
713af91
Bit more
joveeater Apr 10, 2023
0da8198
More more more
joveeater Apr 23, 2023
1110027
MOAR
joveeater Apr 25, 2023
5d5897a
More
joveeater Apr 25, 2023
6bcf8eb
even more
joveeater Apr 27, 2023
60c2393
style: typo `item_spawn` -> `item::spawn`
scarf005 Apr 27, 2023
50518b2
style: remove unnecessary `std::move`, use `->` for activity
scarf005 Apr 27, 2023
3553401
fix: legacy null item reference
scarf005 Apr 27, 2023
0b12953
docs: return type of reduce_charges
scarf005 Apr 27, 2023
18112e1
style: astyle
scarf005 Apr 27, 2023
bcfe831
Merge pull request #1 from scarf005/copy-elision
joveeater Apr 27, 2023
767c545
Now with compiling
joveeater May 5, 2023
189100b
More fixes
joveeater May 5, 2023
0209ed3
More fixes
joveeater May 6, 2023
6d6a28f
Pre-merge commit, fairly stable now
joveeater May 7, 2023
4bd3a36
Round out interfaces
joveeater May 7, 2023
c82307f
All merged up
joveeater May 7, 2023
8c1c36a
Better vehicles and cleanup
joveeater May 7, 2023
cd3aa3d
Remove traces and better destruction
joveeater May 7, 2023
c5ea05a
Attempt to appease gcc with vectors
joveeater May 7, 2023
4b624a5
Pretty sure this wasn't me but ok
joveeater May 7, 2023
b9c775c
ty clang tidy
joveeater May 7, 2023
a40f45f
Oh yeah sounds exist
joveeater May 7, 2023
f0b724c
bug fix
joveeater May 8, 2023
74a2366
More merging
joveeater May 8, 2023
7138c39
Remove unused overmap constructors as they fail on some compilers
joveeater May 8, 2023
0fe91b6
Backwards compat
joveeater May 8, 2023
23d1af1
Test suite compiles now
joveeater May 9, 2023
1567f4a
MOAR
joveeater May 15, 2023
2225190
More more more
joveeater May 16, 2023
e9f6c96
Test suite passes
joveeater May 18, 2023
075d984
Merge branch 'upload' into spring-refactor
joveeater May 18, 2023
0a196b6
Bad move
joveeater May 18, 2023
9514ef2
Fix missing super character constructors
joveeater May 18, 2023
0e55826
Update init.cpp
joveeater May 18, 2023
5490d6c
Update src/init.cpp
joveeater May 18, 2023
a3018d2
Update src/init.cpp
joveeater May 18, 2023
a1d4fdc
Update init.cpp
joveeater May 18, 2023
f6fef39
Merge remote-tracking branch 'upstream/deferred-loading-ub' into spri…
joveeater May 18, 2023
94efd3b
Remove unused stuff
joveeater May 18, 2023
a1a6935
And the missed use
joveeater May 18, 2023
23c81f8
Remove execinfo.h
joveeater May 18, 2023
c320530
Bugs
joveeater May 19, 2023
4c6c5f2
Fix map rotation
joveeater May 19, 2023
d6f27b0
Fix failed wrecks
joveeater May 19, 2023
582bf36
More bugfixes
joveeater May 20, 2023
964b03b
Various bugs
joveeater May 20, 2023
5cf4e29
Merge branch 'upload' into spring-refactor
joveeater May 20, 2023
3b1678f
More bugfixes
joveeater May 20, 2023
312d122
Fix disassembly
joveeater May 20, 2023
ae159f1
Fix dead removals
joveeater May 21, 2023
d42f9c5
Back to late delete for now
joveeater May 21, 2023
7775c98
Missing property in constructor
joveeater May 21, 2023
4ed4d17
Activity fix
joveeater May 21, 2023
a05a51c
More safety
joveeater May 21, 2023
fe65d83
style: format with code blocks
scarf005 May 22, 2023
e2708b5
ups
joveeater May 22, 2023
d2017f1
Merge branch 'upload' into spring-refactor
joveeater May 22, 2023
d7ce52f
Update crafting.cpp
joveeater May 22, 2023
72dcc85
More fixes
joveeater May 22, 2023
a57239f
More fixes
joveeater May 23, 2023
b319e78
Forgot to add a file
joveeater May 23, 2023
3e5ccaa
Fix rotation offsets
joveeater May 23, 2023
6fcf9f8
Merge pull request #3 from scarf005/game-objects-docs
joveeater May 24, 2023
64bccc0
Appease gcc
joveeater May 24, 2023
f856c69
Fixup android
joveeater May 24, 2023
7b8782f
minor fixes
joveeater May 24, 2023
eb44b19
weapon charges fix
joveeater May 25, 2023
bddeec4
Fix monsters
joveeater May 26, 2023
fe9fe2f
Remove old rotation offsets
joveeater May 26, 2023
fc8daca
Fixes
joveeater May 26, 2023
d222b27
minor safety, needs investigating
joveeater Jun 3, 2023
3292b58
Merge branch 'upload' into spring-refactor
joveeater Jun 20, 2023
6689a63
Merge branch 'upload' into spring-refactor, not done yet
joveeater Jul 14, 2023
cbb5bfd
Merge branch 'upload' into spring-refactor
joveeater Jul 15, 2023
c107a27
Fixes
joveeater Jul 18, 2023
7fd408d
Merge branch 'upload' into spring-refactor
joveeater Jul 19, 2023
cc3137b
cleanup
joveeater Jul 19, 2023
daaffe1
pch fix and more cleanup
joveeater Jul 19, 2023
10d1eeb
Merge branch 'upload' into spring-refactor
scarf005 Jul 20, 2023
1dc2409
Merge branch 'upload' into spring-refactor
joveeater Jul 20, 2023
867f96e
merge
joveeater Jul 21, 2023
152c389
Fix msvc
joveeater Jul 21, 2023
b26ea16
Fix spacing, remove unused includes
olanti-p Jul 23, 2023
a4e599f
Remove npc.h include from locations.h
olanti-p Jul 23, 2023
fc35e9a
Remove leftovers from item_location
olanti-p Jul 23, 2023
b5c73b7
Remove old commented code
olanti-p Jul 23, 2023
2d07409
Remove player_activity.h from json.h
olanti-p Jul 23, 2023
97054bb
Split off activity_ptr into its own header
olanti-p Jul 23, 2023
8bf8a5d
Fix typos
olanti-p Jul 23, 2023
cf2510f
Remove commented out or dead code
olanti-p Jul 23, 2023
8edf510
Fix tidy warnings
olanti-p Jul 23, 2023
1e92947
Remove colony from update-pch.sh
joveeater Jul 24, 2023
2f1bc14
Merge pull request #4 from olanti-p/item-identity-23-07-2023
joveeater Jul 24, 2023
c2f88d3
Merge remote-tracking branch 'origin/spring-refactor' into spring-ref…
joveeater Jul 24, 2023
fddf2c5
Hopefully this fixes the compile
joveeater Jul 24, 2023
945a5fe
build fixes
joveeater Jul 25, 2023
1c9190d
Wrap long comments
olanti-p Jul 25, 2023
1ada61e
Fix typo
olanti-p Jul 25, 2023
29acbc7
Delete submodule
olanti-p Jul 25, 2023
1d0205f
Alternative build fix
olanti-p Jul 25, 2023
8118233
Fix dereferencing nullptr
olanti-p Jul 25, 2023
05249cf
Remove extra space
olanti-p Jul 25, 2023
3e7373d
Remove dead code
olanti-p Jul 25, 2023
277c068
Update src/detached_ptr.cpp
joveeater Jul 25, 2023
1f3dbe1
Update src/activity_actor.cpp
joveeater Jul 25, 2023
000c5a0
Update src/active_tile_data.cpp
joveeater Jul 25, 2023
afc06ac
Update src/handle_liquid.h
joveeater Jul 25, 2023
cb6ee3a
Merge pull request #5 from olanti-p/item-identity-25-07-2023
joveeater Jul 25, 2023
82fbdab
Update src/active_tile_data.cpp
joveeater Jul 25, 2023
b1075e7
Fix takeoff deleting items
joveeater Jul 25, 2023
f76b178
Fixes
joveeater Jul 25, 2023
1f67b88
Liquid fix
joveeater Jul 26, 2023
a1e2bdd
Fix book crash
joveeater Jul 26, 2023
7c0f646
fix holsters
joveeater Jul 26, 2023
ba4e860
Merge branch 'upload' into spring-refactor
joveeater Aug 10, 2023
91d2a78
missed a spot
joveeater Aug 10, 2023
360d121
Merge branch 'upload' into spring-refactor
joveeater Aug 16, 2023
5c371ed
Merge remote-tracking branch 'upstream/upload' into spring-refactor
scarf005 Aug 29, 2023
8b574d4
fix: make it compile
scarf005 Aug 29, 2023
0f04a09
Merge branch 'upload' into spring-refactor
joveeater Sep 11, 2023
1e4f856
Merge branch 'spring-lua' into spring-refactor
joveeater Sep 11, 2023
b06506d
Mess with lua iterators
joveeater Sep 12, 2023
2d1b37f
Merge remote-tracking branch 'upstream/upload' into spring-refactor
scarf005 Sep 23, 2023
09d3f4d
Fixes
joveeater Sep 23, 2023
5531a5a
Merge branch 'spring-refactor' into spring-0.4
scarf005 Sep 23, 2023
3a344ae
fix: iexamine_elevator
scarf005 Sep 23, 2023
6fc592a
fix: `vehicle_part.h` headers
scarf005 Sep 23, 2023
7d94ff7
fix: salvage by weight PR
scarf005 Sep 23, 2023
6d85c7a
docs: game objects
scarf005 Sep 23, 2023
0aee3c8
fix: salvage test
scarf005 Sep 23, 2023
a3b3b47
Merge remote-tracking branch 'upstream/upload' into spring-0.4
scarf005 Sep 23, 2023
d1d29c4
Merge pull request #7 from scarf005/spring-0.4
joveeater Sep 23, 2023
f87a168
style(autofix.ci): automated formatting
autofix-ci[bot] Sep 23, 2023
e6eb11a
submap rotate fixes
joveeater Sep 26, 2023
e5110a6
Merge remote-tracking branch 'origin/spring-refactor' into spring-ref…
joveeater Sep 26, 2023
e9a4cc5
Shouldn't use uint
joveeater Sep 27, 2023
bee0ad4
Merge branch 'upload' into spring-refactor
joveeater Sep 27, 2023
f6d0256
And the rest
joveeater Sep 27, 2023
59afa89
Merge branch 'upload' into spring-refactor
joveeater Sep 28, 2023
c25aa04
Merge branch 'upload' into spring-refactor
joveeater Sep 29, 2023
30cd47a
Fix destroyed things being processed
joveeater Sep 30, 2023
9dfd4c8
Fix armor relayering
joveeater Sep 30, 2023
76b1b4f
Merge branch 'upload' into spring-refactor
joveeater Sep 30, 2023
e519498
Merge branch 'upload' into spring-refactor
joveeater Oct 6, 2023
e0dc0bb
Merge branch 'upload' into spring-refactor
joveeater Oct 7, 2023
0b4b6a5
Merge branch 'upload' into spring-refactor
joveeater Oct 8, 2023
b360544
fix gcc
joveeater Oct 8, 2023
c3fc753
style(autofix.ci): automated formatting
autofix-ci[bot] Oct 8, 2023
edbf095
Fix filthy clothes
joveeater Oct 8, 2023
283f7b4
Merge branch 'upload' into spring-refactor
joveeater Oct 8, 2023
6ca5680
Fix butchering
joveeater Oct 8, 2023
c0b956b
Random iterator safety fixes
joveeater Oct 8, 2023
9ef4863
refactor: trailing return goes brrrrr
scarf005 Oct 4, 2023
5a173ee
refactor: apply clang-tidy suggestions
scarf005 Oct 4, 2023
afe72e5
perf: remove obsoleted colony tests
scarf005 Oct 5, 2023
4e3bb46
perf: apply all clang-tidy performance fixes
scarf005 Oct 8, 2023
113373c
perf: use `emplace_back`
scarf005 Oct 8, 2023
b27bd0a
fix: position loopback segfaulting
scarf005 Oct 4, 2023
a75d782
fix: keep location info on `attempt_detach`
scarf005 Oct 8, 2023
56d4229
perf: remove flag usage for temperature display
scarf005 Oct 8, 2023
67c0dfc
feat: give morale bonus for items `EATEN_COLD`
scarf005 Oct 8, 2023
b6725c2
Better position through attempt_detach
joveeater Oct 8, 2023
d2069d7
Merge pull request #11 from scarf005/clang-tidy-perf
joveeater Oct 8, 2023
6d170bc
Update game_object.cpp
joveeater Oct 8, 2023
f94b7f1
Update rot.cpp
joveeater Oct 8, 2023
8144c81
Merge pull request #12 from scarf005/fridges-are-cool
joveeater Oct 8, 2023
bfec42c
style(autofix.ci): automated formatting
autofix-ci[bot] Oct 8, 2023
02fab74
Fix things rotting away
joveeater Oct 8, 2023
9f75cca
Fix null cache references being moved badly
joveeater Oct 9, 2023
9114851
Merge branch 'upload' into spring-refactor
joveeater Oct 9, 2023
791acff
style(autofix.ci): automated formatting
autofix-ci[bot] Oct 9, 2023
c524884
Fix ub when active item list is empty
joveeater Oct 10, 2023
c1a4e8a
Prevents possible use after free in sounds
joveeater Oct 10, 2023
d84aa0a
Merge branch 'sound-ub' into spring-refactor
joveeater Oct 11, 2023
a05cd40
Merge branch 'upload' into spring-refactor
joveeater Oct 15, 2023
9548bbb
Merge branch 'upload' into spring-refactor
joveeater Oct 15, 2023
965c201
Merge branch 'upload' into spring-refactor
joveeater Oct 17, 2023
fdcac04
Appease windows compilers noexcept
joveeater Oct 17, 2023
fc5f888
Bunch of cleanup
joveeater Oct 18, 2023
d00cbc9
Merge branch 'upload' into spring-refactor
joveeater Oct 25, 2023
8a36c8b
Merge branch 'upload' into spring-refactor
joveeater Oct 25, 2023
484b43b
Merge branch 'upload' into spring-refactor
joveeater Oct 25, 2023
adc87f9
Proper move for lambda arg/return
joveeater Oct 25, 2023
f24486e
style(autofix.ci): automated formatting
autofix-ci[bot] Oct 25, 2023
38c027f
Merge branch 'upload' into spring-refactor
joveeater Oct 30, 2023
8bc16fb
Merge remote-tracking branch 'origin/spring-refactor' into spring-ref…
joveeater Oct 30, 2023
e2e7884
tidy
joveeater Nov 2, 2023
09fc616
style(autofix.ci): automated formatting
autofix-ci[bot] Nov 2, 2023
e80a4bc
Merge remote-tracking branch 'cbn/upload' into spring-refactor
olanti-p Nov 2, 2023
26e44a4
Fix or silence misc lints
olanti-p Nov 2, 2023
c73e1c4
Fix accidental copy
olanti-p Nov 2, 2023
27df241
Use somewhat safer deallocation on return
olanti-p Nov 2, 2023
c08c1f6
Fix readability-inconsistent-declaration-parameter-name
olanti-p Nov 2, 2023
3577fe1
Delete doc/GAME_OBJECT.md
olanti-p Nov 2, 2023
13a0587
Use id as debug name to avoid it being translated
olanti-p Nov 2, 2023
0df5689
Fix nullptr access
olanti-p Nov 2, 2023
80cbc96
Add blocks in switch cases
olanti-p Nov 2, 2023
14a353d
Silence false positive use-after-move
olanti-p Nov 3, 2023
6bd1991
Reorder some code to avoid use-after-move
olanti-p Nov 3, 2023
3517cfa
Reorder some code to avoid bugprone-if-assignment
olanti-p Nov 3, 2023
b72697c
Fix moving of references
olanti-p Nov 3, 2023
c78faaf
Remove noop detached_ptr<item>::release() calls
olanti-p Nov 3, 2023
6d79737
Fix legit (?) cases of use-after-move
olanti-p Nov 3, 2023
bd65e2a
Fix crash in inventory dumping
joveeater Nov 3, 2023
e6a7268
Fix bug in spells
joveeater Nov 3, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 70 additions & 0 deletions doc/GAME_OBJECTS.md
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file seems to be a leftover from migration to new docs.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh yeah this is a new doc added for the new features so it won't have been caught by the migration.

Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Game Objects

Many of the things that physically exist within the game world are **game objects(GO)**. Currently
this only covers items, but creatures and vehicles are coming soon and then probably furniture at
some point. GOs have a small common interface with methods like name and position that you can find
in [`game_object.h`](../src/game_object.h). GOs use private constructors, this means **your
variables must always be references or pointers**. Trying to assign a variable without a layer of
indirection like that will cause a compile error. Likewise trying to copy one object over another
will cause a similar error.

```c++
item& it_ref = ...; // Good
item* it_pointer; // Good

item it = ...; // Compile error
it_ref = other; // Compile error
*it_pointer = other; // Compile error
```

New GOs can be created via `::spawn` static methods that return a `detached_ptr` to the newly
created game object. A `detached_ptr` represents an object that does not currently exist in the game
world. There can only be one `detached_ptr` to an object at a time (those who know
[`std::unique_ptr`](https://en.cppreference.com/w/cpp/memory/unique_ptr) will be familiar with this
behavior). Functions that add an object to the world will require that you `std::move` in a
`detached_ptr`. In general `detached_ptr`s must be `std::move`'d when they're passed into a
function. Note that you should never use any variable after it has been moved. Likewise functions
that remove an object from the world will return a `detached_ptr`. This ensures that you can't add
the same thing to the world twice.

Functions that don't add things to the world just accept normal pointers. You can turn a
`detached_ptr` into a normal pointer by doing this. Note that you can use this to keep a valid
pointer to something even after you `std::move` it, but you must do this before the `std::move`
happens.

```c++
&*detached
```

And you can go the other way using this. Though note that it removes the object from the game world
in the process and will cause errors if called on an object that isn't in the game world.

```c++
detached_ptr<item> as_detached=normal_ptr->detach();
```

Trying to access an invalid `detached_ptr` (for instance one that has been `std::move`'d from) will
cause a debugmsg and give you the null version of that object.

## Safe References

Game objects support safe references. `safe_reference<item>` will refuse access to an object that
has been destroyed or is outside of the reality bubble without losing track of it, and they can be
saved and loaded. You must check them as a boolean (e.g. `if( ref )`) to see if they're valid.
Trying to access them when they're not will cause debugmsgs and give you a null object instead. They
have a small interface that lets you check if they're destroyed or unloaded etc. If they were
destroyed or unloaded this turn, they have a method that will allow you to access the object in a
const fashion, for instance to display an error message.

If you're moving objects around you need to use `detached_ptr`s, but otherwise when choosing which
reference to use the most important thing to consider is how long you want to hold onto it. If
you're just using something temporarily, for instance most arguments and variables, you should use a
normal reference or pointer. If you need to store it for longer you should use a safe reference and
this means it can be easily stored in the save file. In the rare case that you do want to save it
across turns but don't want to store it in the save file, which means caches, there's also a fast
`cache_reference<item>`, which does last across turns but can't be saved.

Game objects can sometimes be split into pieces or merged together. Item stacks are the main example
of this but there are others like vehicles being split or dissoluted devourers merging. When a stack
of items is split, the stack that stays in place is the one that safe references will follow. When
they are merged safe references to either half of the merge will now point to the merge result.
1 change: 0 additions & 1 deletion msvc-full-features/stdafx.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@
#include <vector>

#include "../src/platform_win.h"
#include "../src/colony.h"

#if defined(TILES)
# if defined(_MSC_VER) && defined(USE_VCPKG)
Expand Down
1 change: 0 additions & 1 deletion pch/main-pch.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,3 @@
#include <unordered_set>
#include <utility>
#include <vector>
#include "../src/colony.h"
6 changes: 3 additions & 3 deletions src/action.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -556,12 +556,12 @@ bool can_butcher_at( const tripoint &p )
bool has_corpse = false;

const inventory &crafting_inv = you.crafting_inventory();
for( item &items_it : items ) {
if( items_it.is_corpse() ) {
for( item *&items_it : items ) {
if( items_it->is_corpse() ) {
if( factor != INT_MIN || factorD != INT_MIN ) {
has_corpse = true;
}
} else if( crafting::can_disassemble( you, items_it, crafting_inv ).success() ) {
} else if( crafting::can_disassemble( you, *items_it, crafting_inv ).success() ) {
has_item = true;
}
}
Expand Down
99 changes: 42 additions & 57 deletions src/active_item_cache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,62 +9,58 @@
void active_item_cache::remove( const item *it )
{
for( auto &list : active_items ) {
list.second.remove_if( [it]( const item_reference & active_item ) {
item *const target = active_item.item_ref.get();
list.second.erase( std::remove_if( list.second.begin(),
list.second.end(), [it]( const cache_reference<item> &active_item ) {
if( !active_item ) {
return true;
}
item *const target = &*active_item;
return !target || target == it;
} );
} ), list.second.end() );
}
if( it->can_revive() ) {
special_items[ special_item_type::corpse ].remove_if( [it]( const item_reference & active_item ) {
item *const target = active_item.item_ref.get();
return !target || target == it;
} );
std::vector<cache_reference<item>> &corpse = special_items[ special_item_type::corpse ];
corpse.erase( std::remove( corpse.begin(), corpse.end(), it ), corpse.end() );
}
if( it->get_use( "explosion" ) ) {
special_items[ special_item_type::explosive ].remove_if( [it]( const item_reference &
active_item ) {
item *const target = active_item.item_ref.get();
return !target || target == it;
} );
std::vector<cache_reference<item>> &explosive = special_items[ special_item_type::explosive ];
explosive.erase( std::remove( explosive.begin(), explosive.end(), it ), explosive.end() );
}
}

void active_item_cache::add( item &it, point location )
void active_item_cache::add( item &it )
{
// If the item is alread in the cache for some reason, don't add a second reference
std::list<item_reference> &target_list = active_items[it.processing_speed()];
if( std::find_if( target_list.begin(),
target_list.end(), [&it]( const item_reference & active_item_ref ) {
return &it == active_item_ref.item_ref.get();
} ) != target_list.end() ) {
std::vector<cache_reference<item>> &target_list = active_items[it.processing_speed()];
if( std::find( target_list.begin(), target_list.end(), it ) != target_list.end() ) {
return;
}
if( it.can_revive() ) {
special_items[ special_item_type::corpse ].push_back( item_reference{ location, it.get_safe_reference() } );
special_items[ special_item_type::corpse ].push_back( it );
}
if( it.get_use( "explosion" ) ) {
special_items[ special_item_type::explosive ].push_back( item_reference{ location, it.get_safe_reference() } );
special_items[ special_item_type::explosive ].push_back( it );
}
target_list.push_back( item_reference{ location, it.get_safe_reference() } );
target_list.push_back( it );
}

bool active_item_cache::empty() const
{
for( std::pair<int, std::list<item_reference>> active_queue : active_items ) {
for( std::pair<int, std::vector<cache_reference<item>>> active_queue : active_items ) {
if( !active_queue.second.empty() ) {
return false;
}
}
return true;
}

std::vector<item_reference> active_item_cache::get()
std::vector<item *> active_item_cache::get()
{
std::vector<item_reference> all_cached_items;
for( std::pair<const int, std::list<item_reference>> &kv : active_items ) {
for( std::list<item_reference>::iterator it = kv.second.begin(); it != kv.second.end(); ) {
if( it->item_ref ) {
all_cached_items.emplace_back( *it );
std::vector<item *> all_cached_items;
for( std::pair<const int, std::vector<cache_reference<item>>> &kv : active_items ) {
for( std::vector<cache_reference<item>>::iterator it = kv.second.begin(); it != kv.second.end(); ) {
if( *it ) {
all_cached_items.push_back( & **it );
++it;
} else {
it = kv.second.erase( it );
Expand All @@ -74,16 +70,21 @@ std::vector<item_reference> active_item_cache::get()
return all_cached_items;
}

std::vector<item_reference> active_item_cache::get_for_processing()
std::vector<item *> active_item_cache::get_for_processing()
{
std::vector<item_reference> items_to_process;
for( std::pair<const int, std::list<item_reference>> &kv : active_items ) {
std::vector<item *> items_to_process;
for( std::pair < const int, std::vector<cache_reference<item>>> &kv : active_items ) {
// Rely on iteration logic to make sure the number is sane.
int num_to_process = kv.second.size() / kv.first;
std::list<item_reference>::iterator it = kv.second.begin();
std::vector<cache_reference<item>>::iterator it = kv.second.begin();

//TODO!: This is a bit of a hack, at the very least check the maths
//Skip the entries that were processed last turn.
it += num_to_process * ( to_turn<int>( calendar::turn ) % kv.first );

for( ; it != kv.second.end() && num_to_process >= 0; ) {
if( it->item_ref ) {
items_to_process.push_back( *it );
if( *it ) {
items_to_process.push_back( & **it );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's some weird behavior with food vanishing.
In a clear field, if you drop a raw potato in an empty submap and then a raw brains, the brains would stay fresh indefinitely, but if you drop first the brains, then the potato, the brains would vanish after approx. 10 minutes of wait.

This snippet may be related, possible cause:

  1. Have 2 items in cache, both are food, so both should be processed once every 10 minutes (600 turns)
  2. num_to_process is always 2 / 600 = 0
  3. it equals kv.second.begin(), i.e. the 1st food item
  4. num_to_process * ( to_turn<int>( calendar::turn ) % kv.first ) evaluates to 0 because num_to_process is 0
  5. we iterate over the 1st item, then execution stops since num_to_process equals -1
  6. on next turn, we have the same 2 food items, and all the math is the same, so we once again process only the 1st item and ignore the 2nd

The old implementation (commented out a few lines below) worked around this by shuffling processed items to the end of the list, so on the 2nd turn the 2nd item becomes the 1st, and gets updated.

Copy link
Contributor

@olanti-p olanti-p Jul 25, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another issue with vanishing food:

  1. Have 2 different characters in different game worlds
  2. Load character A, debug spawn and drop a raw potato (it has a shelf life of 1 year), save and quit
  3. Without closing the game, load character B, then immediately save and quit
  4. Without closing the game, load character A and take 1 step. The potato vanishes.

--num_to_process;
++it;
} else {
Expand All @@ -93,34 +94,18 @@ std::vector<item_reference> active_item_cache::get_for_processing()
}
// Rotate the returned items to the end of their list so that the items that weren't
// returned this time will be first in line on the next call
kv.second.splice( kv.second.end(), kv.second, kv.second.begin(), it );
// kv.second.splice( kv.second.end(), kv.second, kv.second.begin(), it );
}
return items_to_process;
}

std::vector<item_reference> active_item_cache::get_special( special_item_type type )
{
std::vector<item_reference> matching_items;
for( const item_reference &it : special_items[type] ) {
matching_items.push_back( it );
}
return matching_items;
}

void active_item_cache::subtract_locations( point delta )
{
for( std::pair<const int, std::list<item_reference>> &pair : active_items ) {
for( item_reference &ir : pair.second ) {
ir.location -= delta;
}
}
}

void active_item_cache::rotate_locations( int turns, point dim )
std::vector<item *> active_item_cache::get_special( special_item_type type )
{
for( std::pair<const int, std::list<item_reference>> &pair : active_items ) {
for( item_reference &ir : pair.second ) {
ir.location = ir.location.rotate( turns, dim );
std::vector<item *> matching_items;
for( const cache_reference<item> &it : special_items[type] ) {
if( it ) {
matching_items.push_back( &*it );
}
}
return matching_items;
}
21 changes: 6 additions & 15 deletions src/active_item_cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,6 @@

class item;

// A struct used to uniquely identify an item within a submap or vehicle.
struct item_reference {
point location;
safe_reference<item> item_ref;
};

enum class special_item_type : int {
none,
corpse,
Expand All @@ -37,8 +31,8 @@ struct hash<special_item_type> {
class active_item_cache
{
private:
std::unordered_map<int, std::list<item_reference>> active_items;
std::unordered_map<special_item_type, std::list<item_reference>> special_items;
std::unordered_map<int, std::vector<cache_reference<item>>> active_items;
std::unordered_map<special_item_type, std::vector<cache_reference<item>>> special_items;

public:
/**
Expand All @@ -52,7 +46,7 @@ class active_item_cache
* Adds the reference to the cache. Does nothing if the reference is already in the cache.
* Relies on the fact that item::processing_speed() is a constant.
*/
void add( item &it, point location );
void add( item &it );

/**
* Returns true if the cache is empty
Expand All @@ -63,7 +57,7 @@ class active_item_cache
* Returns a vector of all cached active item references.
* Broken references are removed from the cache.
*/
std::vector<item_reference> get();
std::vector<item *> get();

/**
* Returns the first size() / processing_speed() elements of each list, rounded up.
Expand All @@ -73,15 +67,12 @@ class active_item_cache
* the cache.
* Relies on the fact that item::processing_speed() is a constant.
*/
std::vector<item_reference> get_for_processing();
std::vector<item *> get_for_processing();

/**
* Returns the currently tracked list of special active items.
*/
std::vector<item_reference> get_special( special_item_type type );
/** Subtract delta from every item_reference's location */
void subtract_locations( point delta );
void rotate_locations( int turns, point dim );
std::vector<item *> get_special( special_item_type type );
};

#endif // CATA_SRC_ACTIVE_ITEM_CACHE_H
4 changes: 2 additions & 2 deletions src/active_tile_data.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -256,8 +256,8 @@ void charger_tile::update_internal( time_point to, const tripoint_abs_ms &p,
}
std::int64_t power = this->power * to_seconds<std::int64_t>( to - get_last_updated() );
// TODO: Make not a copy from map.cpp
for( item &outer : sm->get_items( p_within_sm.raw() ) ) {
outer.visit_items( [&power, &grid]( item * it ) {
for( item *const outer : sm->get_items( p_within_sm.raw() ) ) {
outer->visit_items( [&power, &grid]( item * it ) {
item &n = *it;
if( !n.has_flag( flag_RECHARGE ) && !n.has_flag( flag_USE_UPS ) ) {
return VisitResponse::NEXT;
Expand Down
Loading