Files
GabsPuNs-Project_Zenith_Main/Minecraft.Client/StructureTable.cpp
2026-05-14 19:16:33 -04:00

357 lines
10 KiB
C++

#include "stdafx.h"
#include "StructureTable.h"
#include "../Minecraft.World/StringHelpers.h"
unordered_map<wstring, eMinecraftStructureFeature> StructureTable::s_structureFeatureNamesMap;
unordered_map<wstring, eMinecraftStructurePiece> StructureTable::s_structurePieceNamesMap;
unordered_map<wstring, eGenerateObject> StructureTable::s_generateObjectNamesMap;
unordered_map<wstring, eGenerateEntity> StructureTable::s_generateEntityNamesMap;
unordered_map<wstring, eGenerateStructure> StructureTable::s_generateStructureNamesMap;
const wchar_t *StructureTable::StructureFeatureElements[eMinecraftStructureFeature_Count] =
{
L"NOTSET",
L"VillageFeature",
};
const wchar_t *StructureTable::StructurePieceElements[eMinecraftStructurePiece_Count] =
{
L"NOTSET",
L"DesertPyramidPiece",
L"SimpleHouse",
L"SmallTemple",
L"BookHouse",
L"SmallHut",
L"PigHouse",
L"DoubleFarmland",
L"Farmland",
L"Smithy",
L"TwoRoomHouse",
L"LightPost",
L"Well",
};
const wchar_t *StructureTable::GenerateObjectElements[eGenerateObject_Count] =
{
L"Chest",
L"Dispenser",
};
const wchar_t *StructureTable::GenerateEntityElements[eGenerateEntity_Count] =
{
L"Villager",
L"Witch",
};
const wchar_t *StructureTable::GenerateStructureElements[eGenerateStructure_Count] =
{
L"Block",
L"maybeGenerateBlock",
L"AirBox",
L"Box",
L"MaybeBox",
L"UpperHalfSphere",
L"FullSphere",
L"AirColumnUp",
L"fillColumnDown",
L"fillBoxDown",
L"generateAirBoxUp",
L"Crops",
L"CreateDoor",
L"CheckBlock",
};
void StructureTable::staticCtor()
{
for(unsigned int i = 0; i < eMinecraftStructureFeature_Count; ++i)
{
s_structureFeatureNamesMap.insert( unordered_map<wstring,eMinecraftStructureFeature>::value_type( StructureFeatureElements[i], (eMinecraftStructureFeature)i) );
}
for(unsigned int i = 0; i < eMinecraftStructurePiece_Count; ++i)
{
s_structurePieceNamesMap.insert(unordered_map<wstring,eMinecraftStructurePiece>::value_type( StructurePieceElements[i], (eMinecraftStructurePiece)i) );
}
for(unsigned int i = 0; i < eGenerateObject_Count; ++i)
{
s_generateObjectNamesMap.insert( unordered_map<wstring,eGenerateObject>::value_type( GenerateObjectElements[i], (eGenerateObject)i) );
}
for(unsigned int i = 0; i < eGenerateEntity_Count; ++i)
{
s_generateEntityNamesMap.insert( unordered_map<wstring,eGenerateEntity>::value_type( GenerateEntityElements[i], (eGenerateEntity)i) );
}
for(unsigned int i = 0; i < eGenerateStructure_Count; ++i)
{
s_generateStructureNamesMap.insert(unordered_map<wstring,eGenerateStructure>::value_type( GenerateStructureElements[i], (eGenerateStructure)i) );
}
}
StructureTable::StructureTable(PBYTE pbData, DWORD dwLength)
{
loadStructuresFromData(pbData, dwLength);
}
StructureTable::StructurePiece* StructureTable::getStructurePiece(eMinecraftStructurePiece piece)
{
return &m_structurePieces[(int)piece];
}
StructureTable::StructureFeature* StructureTable::getStructureFeature(eMinecraftStructureFeature feature)
{
return &m_structureFeatures[(int)feature];
}
void StructureTable::loadStructuresFromData(PBYTE pbData, DWORD dwLength)
{
byteArray src(pbData, dwLength);
ByteArrayInputStream bais(src);
DataInputStream dis(&bais);
int versionNumber = dis.readInt();
int featureCount = dis.readInt();
int pieceCount = dis.readInt();
for(int i = 0; i < featureCount; ++i)
{
StructureFeature feature;
feature.name = dis.readUTF();
int optionsCount = dis.readInt();
int tilesCount = dis.readInt();
for(int j = 0; j < optionsCount; ++j)
{
feature.options.push_back(dis.readInt());
}
for(int j = 0; j < tilesCount; ++j)
{
std::wstring tile = dis.readUTF();
size_t comma = tile.find(L',');
if(comma != std::wstring::npos)
{
int k = std::stoi(tile.substr(0, comma));
int v = std::stoi(tile.substr(comma + 1));
feature.tiles[k] = v;
}
}
auto it = s_structureFeatureNamesMap.find(feature.name);
if (it != s_structureFeatureNamesMap.end())
{
m_structureFeatures[(int)it->second] = feature;
}
}
for(int i = 0; i < pieceCount; ++i)
{
StructurePiece structurePiece;
structurePiece.name = dis.readUTF();
structurePiece.width = dis.readInt();
structurePiece.height = dis.readInt();
structurePiece.depth = dis.readInt();
int treasureCount = dis.readInt();
int structuresCount = dis.readInt();
int objectsCount = dis.readInt();
int entitiesCount = dis.readInt();
// ?
structurePiece.v8 = dis.readInt();
// @3UR: some sort of count/size?
int unk_count1 = dis.readInt();
int numCropTiles = dis.readInt();
// ?
for(int j = 0; j < unk_count1; ++j)
{
structurePiece.v11.push_back(dis.readInt());
}
for(int j = 0; j < numCropTiles; ++j)
{
structurePiece.cropTiles.push_back(dis.readInt());
}
for(int j = 0; j < treasureCount; ++j)
{
TreasureData t;
t.itemId = dis.readInt();
t.auxValue = dis.readInt();
t.minCount = dis.readInt();
t.maxCount = dis.readInt();
t.weight = dis.readInt();
structurePiece.treasure.push_back(t);
}
for(int j = 0; j < structuresCount; ++j)
{
StructureData s;
std::wstring name = dis.readUTF();
auto it = s_generateStructureNamesMap.find(name);
s.id = (it != s_generateStructureNamesMap.end()) ? (int)it->second : 0;
s.name = name;
s.tileId = dis.readInt();
s.data = dis.readInt();
s.dataType = dis.readInt();
bool hasSecondTile = dis.readBoolean();
if(hasSecondTile)
{
s.secondTileId = dis.readInt();
s.secondData = dis.readInt();
s.secondDataType = dis.readInt();
}
else
{
s.secondTileId = 0;
s.secondData = 0;
s.secondDataType = 0;
}
s.x0 = dis.readInt();
s.y0 = dis.readInt();
s.z0 = dis.readInt();
bool hasBounds = dis.readBoolean();
if(hasBounds)
{
s.x1 = dis.readInt();
s.y1 = dis.readInt();
s.z1 = dis.readInt();
}
else
{
s.x1 = 0;
s.y1 = 0;
s.z1 = 0;
}
// ?
bool hasStartRemaps = dis.readBoolean();
if(hasStartRemaps)
{
s.startRemap0 = dis.readInt();
s.startRemap1 = dis.readInt();
s.startRemap2 = dis.readInt();
}
else
{
s.startRemap0 = -1;
s.startRemap1 = -1;
s.startRemap2 = -1;
}
// ?
bool hasEndRemaps = dis.readBoolean();
if(hasEndRemaps)
{
s.endRemap0 = dis.readInt();
s.endRemap1 = dis.readInt();
s.endRemap2 = dis.readInt();
}
else
{
s.endRemap0 = -1;
s.endRemap1 = -1;
s.endRemap2 = -1;
}
readIntSaveData(dis, s.cropAges);
readIntSaveData(dis, s.v25);
readIntSaveData(dis, s.v26);
readIntSaveData(dis, s.v27);
structurePiece.structures.push_back(s);
}
for(int j = 0; j < objectsCount; ++j)
{
ObjectData o;
std::wstring name = dis.readUTF();
auto it = s_generateObjectNamesMap.find(name);
o.id = (it != s_generateObjectNamesMap.end()) ? (int)it->second : 0;
o.name = name;
o.x = dis.readInt();
o.y = dis.readInt();
o.z = dis.readInt();
o.minEnchantedBooks = dis.readInt();
o.maxEnchantedBooks = dis.readInt();
o.enchantedBookWeight = dis.readInt();
o.rollCount = dis.readInt();
o.canGenEnchantedBooks = dis.readBoolean();
o.rollWeight = dis.readInt();
o.dispenserDir = dis.readInt();
structurePiece.objects.push_back(o);
}
for(int j = 0; j < entitiesCount; ++j)
{
EntityData e;
std::wstring name = dis.readUTF();
auto it = s_generateEntityNamesMap.find(name);
e.id = (it != s_generateEntityNamesMap.end()) ? (int)it->second : 0;
e.x = dis.readInt();
e.y = dis.readInt();
e.z = dis.readInt();
e.count = dis.readInt();
std::wstring professionsCsv = dis.readUTF();
size_t start = 0, end;
while((end = professionsCsv.find(L',', start)) != std::wstring::npos)
{
e.professions.push_back(std::stoi(professionsCsv.substr(start, end - start)));
start = end + 1;
}
if(start < professionsCsv.size())
{
e.professions.push_back(std::stoi(professionsCsv.substr(start)));
}
structurePiece.entities.push_back(e);
}
setStructurePiece(structurePiece.name, structurePiece);
}
bais.reset();
}
void StructureTable::setStructurePiece(const wstring& name, const StructurePiece& piece)
{
auto it = s_structurePieceNamesMap.find(name);
if (it != s_structurePieceNamesMap.end())
{
m_structurePieces[(int)it->second] = piece;
}
}
void StructureTable::readIntSaveData(DataInputStream& dis, vector<int>& container)
{
wstring data = dis.readUTF();
vector<wstring> tokens = stringSplit(data, L',');
for (size_t i = 0; i < tokens.size(); ++i)
{
wistringstream wiss(tokens[i]);
int outVal = 0;
wiss >> dec >> outVal;
container.push_back(outVal);
}
}