feat: add mixBits and latticeHash
This commit is contained in:
1 parent
a7f26fa0ee
commit
cd9eeeddc0
1 file changed
+161
@@ -0,0 +1,161 @@
|
||||
#include "vf/SaveIntegrity.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
|
||||
#include "vf/Block.h"
|
||||
#include "vf/Region.h"
|
||||
|
||||
namespace vf {
|
||||
|
||||
namespace {
|
||||
|
||||
std::string decimal(long long value) { return std::to_string(value); }
|
||||
|
||||
std::string coordText(const Vec3i& coord) {
|
||||
return "(" + decimal(coord.x) + ", " + decimal(coord.y) + ", " + decimal(coord.z) + ")";
|
||||
}
|
||||
|
||||
uint64_t mixBits(uint64_t value) {
|
||||
value += 0x9E3779B97F4A7C15ull;
|
||||
value = (value ^ (value >> 30)) * 0xBF58476D1CE4E5B9ull;
|
||||
value = (value ^ (value >> 27)) * 0x94D049BB133111EBull;
|
||||
return value ^ (value >> 31);
|
||||
}
|
||||
|
||||
uint64_t latticeHash(uint64_t seed, int gx, int gz) {
|
||||
uint64_t h = seed;
|
||||
h = mixBits(h ^ (static_cast<uint64_t>(static_cast<uint32_t>(gx)) * 0x2545F4914F6CDD1Dull));
|
||||
h = mixBits(h ^ (static_cast<uint64_t>(static_cast<uint32_t>(gz)) * 0x9E3779B97F4A7C15ull));
|
||||
return h;
|
||||
}
|
||||
|
||||
int latticeHeight(uint64_t seed, int gx, int gz) {
|
||||
return 32 + static_cast<int>(latticeHash(seed, gx, gz) % 33ull);
|
||||
}
|
||||
|
||||
struct SectorSpan {
|
||||
uint32_t first = 0;
|
||||
uint32_t last = 0;
|
||||
int entryIndex = -1;
|
||||
};
|
||||
|
||||
IntegrityIssue makeIssue(IntegrityIssueKind kind, IssueSeverity severity, std::size_t byteOffset,
|
||||
std::string detail) {
|
||||
IntegrityIssue issue;
|
||||
issue.kind = kind;
|
||||
issue.severity = severity;
|
||||
issue.byteOffset = byteOffset;
|
||||
issue.detail = std::move(detail);
|
||||
return issue;
|
||||
}
|
||||
|
||||
bool actionOutranks(RepairActionKind candidate, RepairActionKind existing) {
|
||||
auto rank = [](RepairActionKind kind) {
|
||||
switch (kind) {
|
||||
case RepairActionKind::RecomputeChecksum: return 0;
|
||||
case RepairActionKind::RegenerateChunk: return 1;
|
||||
case RepairActionKind::RemoveOrphanEntry: return 2;
|
||||
case RepairActionKind::DropChunk: return 3;
|
||||
case RepairActionKind::TruncateBuffer: return 4;
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
return rank(candidate) > rank(existing);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
const char* issueSeverityName(IssueSeverity severity) {
|
||||
switch (severity) {
|
||||
case IssueSeverity::Info: return "info";
|
||||
case IssueSeverity::Warning: return "warning";
|
||||
case IssueSeverity::Recoverable: return "recoverable";
|
||||
case IssueSeverity::Fatal: return "fatal";
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
const char* integrityIssueName(IntegrityIssueKind kind) {
|
||||
switch (kind) {
|
||||
case IntegrityIssueKind::BadMagic: return "badMagic";
|
||||
case IntegrityIssueKind::UnknownVersion: return "unknownVersion";
|
||||
case IntegrityIssueKind::MalformedHeader: return "malformedHeader";
|
||||
case IntegrityIssueKind::TruncatedBuffer: return "truncatedBuffer";
|
||||
case IntegrityIssueKind::ChunkCountOverrun: return "chunkCountOverrun";
|
||||
case IntegrityIssueKind::OrphanEntry: return "orphanEntry";
|
||||
case IntegrityIssueKind::OverlappingEntries: return "overlappingEntries";
|
||||
case IntegrityIssueKind::ChunkOutsideRegion: return "chunkOutsideRegion";
|
||||
case IntegrityIssueKind::ChunkHeightOutOfRange: return "chunkHeightOutOfRange";
|
||||
case IntegrityIssueKind::MalformedRecord: return "malformedRecord";
|
||||
case IntegrityIssueKind::PaletteIndexOutOfRange: return "paletteIndexOutOfRange";
|
||||
case IntegrityIssueKind::ChecksumMismatch: return "checksumMismatch";
|
||||
case IntegrityIssueKind::LightingInconsistent: return "lightingInconsistent";
|
||||
case IntegrityIssueKind::TrailingBytes: return "trailingBytes";
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
const char* repairActionName(RepairActionKind kind) {
|
||||
switch (kind) {
|
||||
case RepairActionKind::DropChunk: return "dropChunk";
|
||||
case RepairActionKind::TruncateBuffer: return "truncateBuffer";
|
||||
case RepairActionKind::RecomputeChecksum: return "recomputeChecksum";
|
||||
case RepairActionKind::RegenerateChunk: return "regenerateChunk";
|
||||
case RepairActionKind::RemoveOrphanEntry: return "removeOrphanEntry";
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
bool IntegrityReport::fatal() const {
|
||||
for (const IntegrityIssue& issue : issues)
|
||||
if (issue.severity == IssueSeverity::Fatal) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IntegrityReport::repairable() const {
|
||||
if (fatal()) return false;
|
||||
for (const IntegrityIssue& issue : issues)
|
||||
if (issue.severity == IssueSeverity::Recoverable) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
std::size_t IntegrityReport::countOf(IntegrityIssueKind kind) const {
|
||||
std::size_t total = 0;
|
||||
for (const IntegrityIssue& issue : issues)
|
||||
if (issue.kind == kind) ++total;
|
||||
return total;
|
||||
}
|
||||
|
||||
std::size_t IntegrityReport::countAtLeast(IssueSeverity severity) const {
|
||||
std::size_t total = 0;
|
||||
for (const IntegrityIssue& issue : issues)
|
||||
if (issue.severity >= severity) ++total;
|
||||
return total;
|
||||
}
|
||||
|
||||
const IntegrityIssue* IntegrityReport::firstOf(IntegrityIssueKind kind) const {
|
||||
for (const IntegrityIssue& issue : issues)
|
||||
if (issue.kind == kind) return &issue;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const RepairAction* RepairPlan::forEntry(int entryIndex) const {
|
||||
for (const RepairAction& action : actions)
|
||||
if (action.entryIndex == entryIndex) return &action;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::size_t RepairPlan::countOf(RepairActionKind kind) const {
|
||||
std::size_t total = 0;
|
||||
for (const RepairAction& action : actions)
|
||||
if (action.kind == kind) ++total;
|
||||
return total;
|
||||
}
|
||||
|
||||
int regeneratedSurfaceHeight(uint64_t seed, int worldX, int worldZ) {
|
||||
int gx = floorDiv(worldX, chunkSize);
|
||||
int gz = floorDiv(worldZ, chunkSize);
|
||||
int fx = floorMod(worldX, chunkSize);
|
||||
int fz = floorMod(worldZ, chunkSize);
|
||||
|
||||
Reference in new issue
Block a user