Otherwise reading some of the records like ESM::CellRef without a subrecord
after could lead to underflow of ESM_Context::leftRec which makes
ESM::ESMReader::hasMoreSubs to return true and load hangs for a while trying to
read the same subrecord many times.
Fix ESM::Variant tests since it's now required to have a record for any ESM
data. Add 16 (size of record header) to all expected data sizes.
Do not add agent bounds which are not supported by recastnavigation with given
settings and log such events.
To avoid reaching navmesh tile generation to find out it can't be generated for
such agent bounds.
Object AABB may be much larger than area currently covered by navmesh. In this
case all tiles beyond covered range should be ignored. Attempt to iterate over
them will not result in any new tile updates but can take quite a while. At
maximum this can be pow(INT_MAX - INT_MIN, 2) iterations.
Use arbitrary time limit to check for update call to finish in the test.
Mostly to avoid string literal lookup by index with iteration over all preciding
literals and calling strlen. This is very inefficient. In genral this makes code
much more straightforward but also makes it portable since now int and float of
different sizes are properly supported.
Round result of std::fmod(hours, 24) to the nearest float below 24 on double to
float conversion when it is not. Add special type and conversion function along
with tests to be used in all places where such conversion happens.
To avoid producing hours equal to 24 due to double to float precision loss.
Fixed some types
removed useless header
applied clang format
fixed compile tests
fixed clang tidy, and closer to logic before this MR
Removed hardcoded refids
unless there is a returned value we don't use static RefIds
can use == between RefId and hardcoded string
Fix clang format
Fixed a few instances where std::string was used, when only const std::string& was needed
removed unused variable
In getMembersLocal(, a reference to a reference wrapper is used, because the id can change, bu all we need to do is change a pointer.No need to change the value
Slowly moving through the open-cs errors
Good progress in openCS
Very good progress on openCS
Getting closer with openCS
OpenCS compiles and runs! Didn't have time to test it all though
ix openMW
everything compiles on windows??
Fix gcc
Fix Clang
Recast functions have preconditions for arguments they don't validate. This may
produce garbage data which may lead to crash. Check arguments and log when they
are invalid.
Do not throw exceptions when these function calls fail, capture Recast reported
errors via RecastContext inherited from rcContext and log them.
NIFFile might not always be created from a file or stream containing NIF data.
Basically there are 2 different responsibilities for this class:
1. Read NIF file
2. Provide input for nifosg and bulletnifloader.
Remove no longer needed NIFFileMock since the state of NIFFfile can be
initialized independently from reading NIF file.
`ciCompareLen(a, b, b.size()) == 0` expression is an equivalent of checking for
equality of `a` prefix with size `b.size()` with `b`.
`ciCompareLen(a, b, a.size()) == 0` is also the same thing but `a` is a prefix
`b` should start with.
Primarily for crossing cell border case. Each Navigator::update call has a cost.
Doing it multiple times per frame increased frame duration on cell loading.
Call Navigator::wait only when cell has changed but do not use
Scene::hasCellChanged because it doesn't always indicates it.
Actors may have different collision shapes. Currently there are axis-aligned
bounding boxes and rotating bounding boxes. With AABB it's required to use
bounding cylinder for navmesh agent to avoid providing paths where actor can't
pass. But for rotating bounding boxes cylinder with diameter equal to the front
face width should be used to not reduce of available paths. For example rats
have rotating bounding box as collision shape because of the difference between
front and side faces width.
* Add agent bounds to navmesh tile db cache key. This is required to distinguish
tiles for agents with different bounds.
* Increase navmesh version because navmesh tile db cache key and data has changed.
* Move navmesh version to the code to avoid misconfiguration by users.
* Fix all places where wrong half extents were used for pathfinding.
Use LRU cache for ESMReaders. When cache capacity is reached close least
recently used ESMReader. Remember the file name if a reader was open. Once the
reader requested again open the file if there is stored name for it. Put
released ESMReader to the back of the free items list. Close ESMReader's from
the front of the free items list.
Cached item can be used only by one client at the same time. If the same item is
requested twice exception is thrown. This should never happen in practice. If
this happens need to fix the client logic.
It's allowed to go over the capacity limit when requesting different readers.
Ideally this should never happen but there will be system error anyway
signalizing about too many open files. Need to fix client logic in this case.
All places that were using a vector of ESMReaders now using the cache. Cache is
local for each use case and there is no need for a thread safety.
Simultaneously writing to sqlite3 database is not possible. Process exclusively
locks the database for this. Another process will fail to perform any request
when database is locked. Alternatively it can wait. Handling this situation
properly requires complexity that is not really needed. Users are not expected
to run multiple openmw processes simultaneously using the same navmeshdb.
Before this change running multiple openmw processes using the same navmeshdb
can lead to a crash when first transaction fails to start because there is
exception thrown and not catched.
Remove use of explicit transactions from DbWorker. Handling all possible
transaction states due to different errors brings unnecessary complexity.
Initially they were introduced to increase time between flushes to disk. This
makes sense for navmeshtool because of massive number of writes but for the
engine this is not an issue.
Need to load the last present record from a sequence of loaded records. That
means reverse should be called before unique or unique should be applied for
a reversed range. Since unique keeps only the first element from a sub
sequence of equal elements.
Use forEachUnique with reversed range to avoid redundant container
modifications.
Use "pragma max_page_count" to define max allowed file size in combination with
"pragma page_size" based on a new setting "max navmeshdb file size".
* Stop navmeshtool on the first db error.
* Disable writes to db in the engine on first "database or disk is full"
SQLite3 error. There is no special error code for this error.
* Change default "write to navmeshdb" to true.
* Use time intervals for transaction duration instead of number of changes.
* Remove tiles outside processing range. Useful when new content profile map
has different bounds.
* Remove ignored tiles. For a case when content profile maps have intersection
but there is no more data for navmesh.
* Remove older tiles at the same worldspace position. If navmesh tile data has
changed with new content, the old ones unlikely to be used.
* Vacuum the database when there are modifications. SQLite leaves empty pages
in the file on database modification. Vacuum cleans up unused pages reducing
the file size.
If object is too big iteration over all tiles covering it can take too much
time. Limit bounds to a square around a player position to cover only tiles
that will be present in navmesh based on max tiles number option.
Each object is associated with a set of tiles its present in. Culling can
reduce this set but it has to be update when bounds change position. Do this
in TileCachedRecastMeshManager::setBounds updating the set and adding/removing
objects to the corresponding CachedRecastMeshManagers.
* Avoid inheritance.
* Define equality operators out of the class definition.
* Replace toString with toStringView where it doesn't make sense to create a string.
Choose a parent base on which node is used to iterate over children nodes.
This leads to duplicate handing of child nodes. A node will be handled so many
times how many parents it has.
For example:
p1 p2
\ /
c
Will be handled as:
p1 p2
| |
c c
If c has children they will be handled X times c is handled.
Perform all request to db in a single thread to avoid blocking navmesh
generator threads due to slow write operations.
Write to db navmesh for all changes except update as it done for memory cache.
Batch multiple db operations into a single transaction to speed up writing by
not executing fsync after each insert/update query. All reads are performed in
the same transaction so they see uncommited data.
Merge conflicts included:
* One setting being removed (branch had changed its type).
* One setting's description being changed (branch had changed its type).
* List of files in components/files was changed both upstream and on the
branch.
* Upstream had changed something in a file the branch deletes.
With this PR we refactor `StringUtils::replaceAll` to accept `string_view` as suggested in a code comment. In addition, while we are touching this rebuild happy file, we slim it down a bit by moving a few sparingly used functions elsewhere.
This PR aims to start addressing `ESM` design issues that have silenced errors we incorporated into groundcover `ESM` loading approaches.
- We move the resolution of `parentFileIndices` from `ESMStore` to `ESMReader` as suggested in a `TODO` comment.
- We improve a highly misleading comment which downplayed the significance of `parentFileIndices`.
- We document important preconditions.
- We move a user facing error message to the highest level and improve its context.
- We remove an inappropriate `setGlobalReaderList` method. We now pass this reader list into the method that requires it.
- We remove a thoroughly pointless optimisation of `Store<ESM::LandTexture>`'s construction that has unnecessarily depended on `getGlobalReaderList`.
There should be no functional changes for `master`, but this PR should remove an issue blocking PR #3208.
To construct serializer from given entities:
* Data source/destination - any value that has to be serialized/deserialized,
usually already existing type.
* Format - functional object to define high level serialization logic to
define specific format and data schema. Like order of fields, allocation.
* Visitor - functional object to define low level serialization logic to
operator on given data part.
* BinaryWriter - copies given value into provided buffer.
* BinaryReader - copies value into given destination from provided buffer.
* SizeAccumulator - calculates required buffer size for given data.