mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2026-10-02 10:53:44 +00:00
feat: web dashboard and playground work
The NexusDashboard-parity dashboard (dDashboardServer) and everything built on it on the experimental branch: accounts, characters, properties and moderation tools, permissions shared with in-game slash commands, economy reports, World 3D and property 3D views with client scenery, scheduled events (features, vanity changes, live events, announcements, restarts), vanity files and events, the CDClient browser, the message inspector with saved captures, chat filter tools, community challenges, live ops, the AI moderator helper, and the server-side changes they need. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -14,6 +14,7 @@
|
||||
#include "CDFeatureGatingTable.h"
|
||||
#include "CDClientManager.h"
|
||||
#include "AssetManager.h"
|
||||
#include "LevelFile.h"
|
||||
#include "ClientVersion.h"
|
||||
#include "dConfig.h"
|
||||
#include <ranges>
|
||||
@@ -28,7 +29,15 @@ Level::Level(Zone* parentZone, const std::string& filepath) {
|
||||
return;
|
||||
}
|
||||
|
||||
ReadChunks(stream);
|
||||
// The file itself is read by LevelFile (dCommon), which the dashboard uses too
|
||||
LevelFile levelFile;
|
||||
levelFile.Read(stream);
|
||||
for (const auto& [id, chunkHeader] : levelFile.chunkHeaders) {
|
||||
Header header;
|
||||
static_cast<LevelFile::ChunkHeader&>(header) = chunkHeader;
|
||||
m_ChunkHeaders.insert(std::make_pair(id, header));
|
||||
}
|
||||
LoadSceneObjects(levelFile.objects);
|
||||
}
|
||||
|
||||
void Level::MakeSpawner(const SceneObject& obj) {
|
||||
@@ -100,123 +109,7 @@ void Level::MakeSpawner(const SceneObject& obj) {
|
||||
Game::zoneManager->MakeSpawner(spawnInfo);
|
||||
}
|
||||
|
||||
void Level::ReadChunks(std::istream& file) {
|
||||
const uint32_t CHNK_HEADER = ('C' + ('H' << 8) + ('N' << 16) + ('K' << 24));
|
||||
|
||||
while (!file.eof()) {
|
||||
uint32_t initPos = uint32_t(file.tellg());
|
||||
uint32_t header = 0;
|
||||
BinaryIO::BinaryRead(file, header);
|
||||
if (header == CHNK_HEADER) { //Make sure we're reading a valid CHNK
|
||||
Header header;
|
||||
BinaryIO::BinaryRead(file, header.id);
|
||||
BinaryIO::BinaryRead(file, header.chunkVersion);
|
||||
BinaryIO::BinaryRead(file, header.chunkType);
|
||||
BinaryIO::BinaryRead(file, header.size);
|
||||
BinaryIO::BinaryRead(file, header.startPosition);
|
||||
|
||||
uint32_t target = initPos + header.size;
|
||||
file.seekg(header.startPosition);
|
||||
|
||||
//We're currently not loading env or particle data
|
||||
if (header.id == ChunkTypeID::FileInfo) {
|
||||
ReadFileInfoChunk(file, header);
|
||||
} else if (header.id == ChunkTypeID::SceneObjectData) {
|
||||
ReadSceneObjectDataChunk(file, header);
|
||||
}
|
||||
|
||||
m_ChunkHeaders.insert(std::make_pair(header.id, header));
|
||||
file.seekg(target);
|
||||
} else {
|
||||
if (initPos == std::streamoff(0)) { //Really old chunk version
|
||||
file.seekg(0);
|
||||
Header header;
|
||||
header.id = ChunkTypeID::FileInfo;
|
||||
BinaryIO::BinaryRead(file, header.chunkVersion);
|
||||
BinaryIO::BinaryRead(file, header.chunkType);
|
||||
uint8_t important = 0;
|
||||
BinaryIO::BinaryRead(file, important);
|
||||
// file.ignore(1); //probably used
|
||||
if (header.chunkVersion > 36) {
|
||||
BinaryIO::BinaryRead(file, header.fileInfo.revision);
|
||||
}
|
||||
// HARDCODED 3
|
||||
if (header.chunkVersion >= 45) file.ignore(4);
|
||||
file.ignore(4 * (4 * 3));
|
||||
|
||||
if (header.chunkVersion >= 31) {
|
||||
if (header.chunkVersion >= 39) {
|
||||
file.ignore(12 * 4);
|
||||
|
||||
if (header.chunkVersion >= 40) {
|
||||
uint32_t s = 0;
|
||||
BinaryIO::BinaryRead(file, s);
|
||||
for (uint32_t i = 0; i < s; ++i) {
|
||||
file.ignore(4 * 3); //a uint and two floats
|
||||
}
|
||||
}
|
||||
} else {
|
||||
file.ignore(8);
|
||||
}
|
||||
|
||||
file.ignore(3 * 4);
|
||||
}
|
||||
|
||||
if (header.chunkVersion >= 36) {
|
||||
file.ignore(3 * 4);
|
||||
}
|
||||
|
||||
if (header.chunkVersion < 42) {
|
||||
file.ignore(3 * 4);
|
||||
|
||||
if (header.chunkVersion >= 33) {
|
||||
file.ignore(4 * 4);
|
||||
}
|
||||
}
|
||||
|
||||
// skydome info
|
||||
uint32_t count = 0;
|
||||
BinaryIO::BinaryRead(file, count);
|
||||
file.ignore(count);
|
||||
|
||||
if (header.chunkVersion >= 33) {
|
||||
for (uint32_t i = 0; i < 5; ++i) {
|
||||
uint32_t count = 0;
|
||||
BinaryIO::BinaryRead(file, count);
|
||||
file.ignore(count);
|
||||
}
|
||||
}
|
||||
// editor settings
|
||||
if (!important && header.chunkVersion >= 37){
|
||||
file.ignore(4);
|
||||
|
||||
uint32_t count = 0;
|
||||
BinaryIO::BinaryRead(file, count);
|
||||
file.ignore(count * 12);
|
||||
|
||||
}
|
||||
|
||||
header.id = ChunkTypeID::SceneObjectData;
|
||||
header.fileInfo.version = header.chunkVersion;
|
||||
ReadSceneObjectDataChunk(file, header);
|
||||
m_ChunkHeaders.insert(std::make_pair(header.id, header));
|
||||
} break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Level::ReadFileInfoChunk(std::istream& file, Header& header) {
|
||||
BinaryIO::BinaryRead(file, header.fileInfo.version);
|
||||
BinaryIO::BinaryRead(file, header.fileInfo.revision);
|
||||
BinaryIO::BinaryRead(file, header.fileInfo.enviromentChunkStart);
|
||||
BinaryIO::BinaryRead(file, header.fileInfo.objectChunkStart);
|
||||
BinaryIO::BinaryRead(file, header.fileInfo.particleChunkStart);
|
||||
}
|
||||
|
||||
void Level::ReadSceneObjectDataChunk(std::istream& file, Header& header) {
|
||||
uint32_t objectsCount = 0;
|
||||
BinaryIO::BinaryRead(file, objectsCount);
|
||||
|
||||
void Level::LoadSceneObjects(const std::vector<SceneObject>& objects) {
|
||||
CDFeatureGatingTable* featureGatingTable = CDClientManager::GetTable<CDFeatureGatingTable>();
|
||||
|
||||
CDFeatureGating gating;
|
||||
@@ -229,28 +122,7 @@ void Level::ReadSceneObjectDataChunk(std::istream& file, Header& header) {
|
||||
|
||||
const auto zoneControlObject = Game::zoneManager->GetZoneControlObject();
|
||||
DluAssert(zoneControlObject != nullptr);
|
||||
for (uint32_t i = 0; i < objectsCount; ++i) {
|
||||
std::u16string ldfString;
|
||||
SceneObject obj;
|
||||
BinaryIO::BinaryRead(file, obj.id);
|
||||
BinaryIO::BinaryRead(file, obj.lot);
|
||||
|
||||
if (header.fileInfo.version >= 38) {
|
||||
int32_t tmp = 1;
|
||||
BinaryIO::BinaryRead(file, tmp);
|
||||
if (tmp > -1 && tmp < 11) obj.nodeType = tmp;
|
||||
}
|
||||
|
||||
if (header.fileInfo.version >= 32) {
|
||||
BinaryIO::BinaryRead(file, obj.glomId);
|
||||
}
|
||||
|
||||
BinaryIO::BinaryRead(file, obj.position);
|
||||
BinaryIO::BinaryRead(file, obj.rotation);
|
||||
BinaryIO::BinaryRead(file, obj.scale);
|
||||
BinaryIO::ReadString<uint32_t>(file, ldfString);
|
||||
BinaryIO::BinaryRead(file, obj.value3);
|
||||
|
||||
for (const auto& obj : objects) {
|
||||
//This is a little bit of a bodge, but because the alpha client (HF) doesn't store the
|
||||
//spawn position / rotation like the later versions do, we need to check the LOT for the spawn pos & set it.
|
||||
if (obj.lot == LOT_MARKER_PLAYER_START) {
|
||||
@@ -258,11 +130,6 @@ void Level::ReadSceneObjectDataChunk(std::istream& file, Header& header) {
|
||||
Game::zoneManager->GetZoneMut()->SetSpawnRot(obj.rotation);
|
||||
}
|
||||
|
||||
for (const auto& token : GeneralUtils::SplitString(GeneralUtils::UTF16ToWTF8(ldfString), '\n')) {
|
||||
obj.settings.ParseInsert(token);
|
||||
}
|
||||
|
||||
|
||||
// We should never have more than 1 zone control object
|
||||
bool skipLoadingObject = obj.lot == zoneControlObject->GetLOT();
|
||||
for (const auto& data : obj.settings | std::views::values) {
|
||||
|
||||
Reference in New Issue
Block a user