Merge branch 'allinone'
This commit is contained in:
commit
f15bd457d3
@ -74,18 +74,11 @@ charname=Pseuwow
|
||||
|
||||
|
||||
// Client emulation configuration
|
||||
// Client 0: Classic WoW 1.12.2 Build 6005
|
||||
// Client 1: TBC 2.4.3 Build 8606
|
||||
// Client 2: WoTLK 3.3.5 Build 12340
|
||||
// Client 3: Cata 4.x.x Build XXX NOT IMPLEMENTED
|
||||
// !!!!
|
||||
// !!!! WARNING!!!! For all of the above Client Version and Client Build are IGNORED
|
||||
// !!!!
|
||||
// Client 9: Custom Settings for Client Version and Client Build
|
||||
// Client 1: Classic WoW 1.12.2 Build 6005
|
||||
// Client 2: TBC 2.4.3 Build 8606
|
||||
// Client 3: WoTLK 3.3.5 Build 12340
|
||||
// Client 4: Cata 4.x.x Build XXX NOT IMPLEMENTED
|
||||
Client=0
|
||||
// Uncomment if you use Client=9
|
||||
// ClientVersion=3.3.5
|
||||
// ClientBuild=12340
|
||||
|
||||
ClientLanguage=enGB
|
||||
// or change to enGB, deDE, ...
|
||||
|
||||
@ -861,11 +861,11 @@ DefReturnResult DefScriptPackage::SCGetObjectValue(CmdSet &Set)
|
||||
else
|
||||
{
|
||||
if(DefScriptTools::stringToLower(Set.arg[1]) == "f")
|
||||
return toString((ldbl)o->GetFloatValue(v));
|
||||
return toString((ldbl)o->GetFloatValue((UpdateFieldName)v));
|
||||
else if(DefScriptTools::stringToLower(Set.arg[1]) == "i64")
|
||||
return toString(o->GetUInt64Value(v));
|
||||
return toString(o->GetUInt64Value((UpdateFieldName)v));
|
||||
else
|
||||
return toString((uint64)o->GetUInt32Value(v));
|
||||
return toString((uint64)o->GetUInt32Value((UpdateFieldName)v));
|
||||
}
|
||||
}
|
||||
return "";
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
// #define _DEBUG 1
|
||||
#include <iostream>
|
||||
#include "MemoryDataHolder.h"
|
||||
#include "MemoryInterface.h"
|
||||
@ -51,187 +52,288 @@ IAnimatedMesh* CM2MeshFileLoader::createMesh(io::IReadFile* file)
|
||||
|
||||
return AnimatedMesh;
|
||||
}
|
||||
void CM2MeshFileLoader::ReadVertices()
|
||||
{
|
||||
//Vertices. Global data
|
||||
if(!M2MVertices.empty())
|
||||
M2MVertices.clear();
|
||||
|
||||
ModelVertex tempM2MVert;
|
||||
f32 tempYZ;
|
||||
MeshFile->seek(header.ofsVertices);
|
||||
|
||||
for(u32 i =0;i<header.nVertices;i++)
|
||||
{
|
||||
MeshFile->read(&tempM2MVert,sizeof(ModelVertex));
|
||||
tempYZ = tempM2MVert.pos.Y;
|
||||
tempM2MVert.pos.Y=tempM2MVert.pos.Z;
|
||||
tempM2MVert.pos.Z=tempYZ;
|
||||
tempYZ = tempM2MVert.normal.Y;
|
||||
tempM2MVert.normal.Y=tempM2MVert.normal.Z;
|
||||
tempM2MVert.normal.Z=tempYZ;
|
||||
|
||||
M2MVertices.push_back(tempM2MVert);
|
||||
}
|
||||
DEBUG(logdebug("Read %u/%u Vertices",M2MVertices.size(),header.nVertices));
|
||||
}
|
||||
|
||||
void CM2MeshFileLoader::ReadViewData(io::IReadFile* file)
|
||||
{
|
||||
//Vertex indices of a specific view.Local to View 0
|
||||
if(M2MIndices.size()>0)
|
||||
M2MIndices.clear();
|
||||
|
||||
u16 tempM2Index;
|
||||
file->seek(currentView.ofsIndex);
|
||||
for(u32 i =0;i<currentView.nIndex;i++)
|
||||
{
|
||||
file->read(&tempM2Index,sizeof(u16));
|
||||
M2MIndices.push_back(tempM2Index);
|
||||
}
|
||||
DEBUG(logdebug("Read %u/%u Indices",M2MIndices.size(),currentView.nIndex));
|
||||
|
||||
//Triangles. Data Points point to the Vertex Indices, not the vertices themself. 3 Points = 1 Triangle, Local to View 0
|
||||
if(M2MTriangles.size()>0)
|
||||
M2MTriangles.clear();
|
||||
|
||||
u16 tempM2Triangle;
|
||||
file->seek(currentView.ofsTris);
|
||||
for(u32 i =0;i<currentView.nTris;i++)
|
||||
{
|
||||
file->read(&tempM2Triangle,sizeof(u16));
|
||||
M2MTriangles.push_back(tempM2Triangle);
|
||||
}
|
||||
DEBUG(logdebug("Read %u/%u Triangles",M2MTriangles.size(),currentView.nTris));
|
||||
//Submeshes, Local to View 0
|
||||
if(M2MSubmeshes.size()>0)
|
||||
M2MSubmeshes.clear();
|
||||
|
||||
ModelViewSubmesh tempM2Submesh;
|
||||
file->seek(currentView.ofsSub);
|
||||
for(u32 i =0;i<currentView.nSub;i++)
|
||||
{
|
||||
file->read(&tempM2Submesh,sizeof(ModelViewSubmesh)-(header.version==0x100?16:0));
|
||||
M2MSubmeshes.push_back(tempM2Submesh);
|
||||
// std::cout<< "Submesh " <<i<<" ID "<<tempM2Submesh.meshpartId<<" starts at V/T "<<tempM2Submesh.ofsVertex<<"/"<<tempM2Submesh.ofsTris<<" and has "<<tempM2Submesh.nVertex<<"/"<<tempM2Submesh.nTris<<" V/T\n";
|
||||
}
|
||||
DEBUG(logdebug("Read %u/%u Submeshes",M2MSubmeshes.size(),currentView.nSub));
|
||||
|
||||
//Texture units. Local to view 0
|
||||
TextureUnit tempM2TexUnit;
|
||||
if(!M2MTextureUnit.empty())
|
||||
{
|
||||
M2MTextureUnit.clear();
|
||||
}
|
||||
file->seek(currentView.ofsTex);
|
||||
for(u32 i=0;i<currentView.nTex;i++)
|
||||
{
|
||||
file->read(&tempM2TexUnit,sizeof(TextureUnit));
|
||||
M2MTextureUnit.push_back(tempM2TexUnit);
|
||||
DEBUG(logdebug(" TexUnit %u: Submesh: %u %u Render Flag: %u TextureUnitNumber: %u %u TTU: %u",i,tempM2TexUnit.submeshIndex1,tempM2TexUnit.submeshIndex2, tempM2TexUnit.renderFlagsIndex, tempM2TexUnit.TextureUnitNumber, tempM2TexUnit.TextureUnitNumber2 ,tempM2TexUnit.textureIndex));
|
||||
}
|
||||
DEBUG(logdebug("Read %u Texture Unit entries for View 0",M2MTextureUnit.size()));
|
||||
|
||||
}
|
||||
|
||||
void CM2MeshFileLoader::ReadTextureDefinitions()
|
||||
{
|
||||
//Texture Lookup table. This is global data
|
||||
u16 tempM2TexLookup;
|
||||
if(!M2MTextureLookup.empty())
|
||||
{
|
||||
M2MTextureLookup.clear();
|
||||
}
|
||||
MeshFile->seek(header.ofsTexLookup);
|
||||
for(u32 i=0;i<header.nTexLookup;i++)
|
||||
{
|
||||
MeshFile->read(&tempM2TexLookup,sizeof(u16));
|
||||
M2MTextureLookup.push_back(tempM2TexLookup);
|
||||
DEBUG(logdebug("Texture %u Type %u",i,tempM2TexLookup));
|
||||
}
|
||||
DEBUG(logdebug("Read %u Texture lookup entries",M2MTextureLookup.size()));
|
||||
|
||||
//Texture Definitions table. This is global data
|
||||
TextureDefinition tempM2TexDef;
|
||||
if(!M2MTextureDef.empty())
|
||||
{
|
||||
M2MTextureDef.clear();
|
||||
}
|
||||
MeshFile->seek(header.ofsTextures);
|
||||
for(u32 i=0;i<header.nTextures;i++)
|
||||
{
|
||||
MeshFile->read(&tempM2TexDef,sizeof(TextureDefinition));
|
||||
M2MTextureDef.push_back(tempM2TexDef);
|
||||
DEBUG(logdebug("Texture %u Type %u",i,tempM2TexDef.texType));
|
||||
}
|
||||
DEBUG(logdebug("Read %u Texture Definition entries",M2MTextureDef.size()));
|
||||
|
||||
//Render Flags table. This is global data
|
||||
RenderFlags tempM2RF;
|
||||
if(!M2MRenderFlags.empty())
|
||||
{
|
||||
M2MRenderFlags.clear();
|
||||
}
|
||||
MeshFile->seek(header.ofsTexFlags);
|
||||
for(u32 i=0;i<header.nTexFlags;i++)
|
||||
{
|
||||
MeshFile->read(&tempM2RF,sizeof(RenderFlags));
|
||||
M2MRenderFlags.push_back(tempM2RF);
|
||||
DEBUG(logdebug("Flag %u: (%u, %u)",i,tempM2RF.blending,tempM2RF.flags));
|
||||
}
|
||||
DEBUG(logdebug("Read %u Renderflags",M2MRenderFlags.size()));
|
||||
|
||||
if(!M2MTextureFiles.empty())
|
||||
M2MTextureFiles.clear();
|
||||
|
||||
std::string tempTexFileName="";
|
||||
M2MTextureFiles.reallocate(M2MTextureDef.size());
|
||||
for(u32 i=0; i<M2MTextureDef.size(); i++)
|
||||
{
|
||||
tempTexFileName.resize(M2MTextureDef[i].texFileLen + 1);
|
||||
MeshFile->seek(M2MTextureDef[i].texFileOfs);
|
||||
MeshFile->read((void*)tempTexFileName.data(),M2MTextureDef[i].texFileLen);
|
||||
M2MTextureFiles.push_back("");
|
||||
M2MTextureFiles[i]=tempTexFileName.c_str();
|
||||
DEBUG(logdebug("Texture: %u %u (%s/%s) @ %u(%u)",i,M2MTextureFiles.size(),M2MTextureFiles[i].c_str(),tempTexFileName.c_str(),M2MTextureDef[i].texFileOfs,M2MTextureDef[i].texFileLen));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool CM2MeshFileLoader::load()
|
||||
{
|
||||
DEBUG(logdebug("Trying to open file %s",MeshFile->getFileName()));
|
||||
|
||||
|
||||
MeshFile->read(&header,sizeof(ModelHeader));
|
||||
if (header.version[0] != 8 || header.version[1] != 1 || header.version[2] != 0 || header.version[3] != 0) {
|
||||
logerror("M2: [%s] Wrong header! File version doesn't match or file is not a M2 file.",MeshFile->getFileName());
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG(logdebug("header okay"));
|
||||
}
|
||||
//Name -> not very important I think, but save it nontheless;
|
||||
//M2MeshName.clear();
|
||||
//M2MeshName.reserve(header.nameLength);
|
||||
//file->seek(header.nameOfs);
|
||||
//file->read(&M2MeshName[0],header.nameLength);
|
||||
//std::cout << "Read name:"<<M2MeshName.c_str()<<"Size: "<< M2MeshName.size() <<"|"<<M2MeshName[0]<< "\n";
|
||||
//logger->log("Mesh Name",M2MeshName.c_str(),ELL_INFORMATION);
|
||||
//Now we load all kinds of data from the file
|
||||
MeshFile->read(&header,20);
|
||||
DEBUG(logdebug("M2 Version %X",header.version));
|
||||
|
||||
switch(header.version)
|
||||
{
|
||||
case 0x100:
|
||||
case 0x104://HACK
|
||||
case 0x105://HACK
|
||||
case 0x106://HACK
|
||||
case 0x107://HACK
|
||||
{
|
||||
MeshFile->read((u8*)&header+20,sizeof(ModelHeader)-20);
|
||||
ReadVertices();
|
||||
MeshFile->seek(header.ofsViews);
|
||||
MeshFile->read(¤tView,sizeof(ModelView));
|
||||
ReadViewData(MeshFile);
|
||||
ReadTextureDefinitions();
|
||||
break;
|
||||
}
|
||||
case 0x108:
|
||||
{
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
logerror("M2: [%s] Wrong header %0X! File version doesn't match or file is not a M2 file.",MeshFile->getFileName(),header.version);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
//Vertices. Global data
|
||||
if(!M2MVertices.empty())
|
||||
M2MVertices.clear();
|
||||
|
||||
ModelVertex tempM2MVert;
|
||||
f32 tempYZ;
|
||||
MeshFile->seek(header.ofsVertices);
|
||||
|
||||
for(u32 i =0;i<header.nVertices;i++)
|
||||
{
|
||||
MeshFile->read(&tempM2MVert,sizeof(ModelVertex));
|
||||
tempYZ = tempM2MVert.pos.Y;
|
||||
tempM2MVert.pos.Y=tempM2MVert.pos.Z;
|
||||
tempM2MVert.pos.Z=tempYZ;
|
||||
tempYZ = tempM2MVert.normal.Y;
|
||||
tempM2MVert.normal.Y=tempM2MVert.normal.Z;
|
||||
tempM2MVert.normal.Z=tempYZ;
|
||||
|
||||
M2MVertices.push_back(tempM2MVert);
|
||||
}
|
||||
DEBUG(logdebug("Read %u/%u Vertices",M2MVertices.size(),header.nVertices));
|
||||
// if(!M2MVertices.empty())
|
||||
// M2MVertices.clear();
|
||||
//
|
||||
// ModelVertex tempM2MVert;
|
||||
// f32 tempYZ;
|
||||
// MeshFile->seek(header.ofsVertices);
|
||||
//
|
||||
// for(u32 i =0;i<header.nVertices;i++)
|
||||
// {
|
||||
// MeshFile->read(&tempM2MVert,sizeof(ModelVertex));
|
||||
// tempYZ = tempM2MVert.pos.Y;
|
||||
// tempM2MVert.pos.Y=tempM2MVert.pos.Z;
|
||||
// tempM2MVert.pos.Z=tempYZ;
|
||||
// tempYZ = tempM2MVert.normal.Y;
|
||||
// tempM2MVert.normal.Y=tempM2MVert.normal.Z;
|
||||
// tempM2MVert.normal.Z=tempYZ;
|
||||
//
|
||||
// M2MVertices.push_back(tempM2MVert);
|
||||
// }
|
||||
// DEBUG(logdebug("Read %u/%u Vertices",M2MVertices.size(),header.nVertices));
|
||||
|
||||
//Views (skins) == Sets of vertices. Usage yet unknown. Global data
|
||||
|
||||
std::string SkinName = MeshFile->getFileName();
|
||||
SkinName = SkinName.substr(0, SkinName.length()-3) + "00.skin"; // FIX ME (and stuffextract) ! as we need more skins
|
||||
io::IReadFile* SkinFile = io::IrrCreateIReadFileBasic(Device, SkinName.c_str());
|
||||
if (!SkinFile)
|
||||
{
|
||||
logerror("Error! Skin file not found: %s", SkinName.c_str());
|
||||
return 0;
|
||||
}
|
||||
|
||||
ModelView currentView;
|
||||
SkinFile->read(¤tView, sizeof(ModelView));
|
||||
|
||||
//std::cout << "Skins "<<header.nViews<<" (views)\n";
|
||||
|
||||
DEBUG(logdebug("Using View 0 for all further operations"));
|
||||
DEBUG(logdebug("This View has %u Submeshes",currentView.nSub));
|
||||
|
||||
//Vertex indices of a specific view.Local to View 0
|
||||
if(M2MIndices.size()>0)
|
||||
M2MIndices.clear();
|
||||
|
||||
u16 tempM2Index;
|
||||
SkinFile->seek(currentView.ofsIndex);
|
||||
for(u32 i =0;i<currentView.nIndex;i++)
|
||||
{
|
||||
SkinFile->read(&tempM2Index,sizeof(u16));
|
||||
M2MIndices.push_back(tempM2Index);
|
||||
}
|
||||
DEBUG(logdebug("Read %u/%u Indices",M2MIndices.size(),currentView.nIndex));
|
||||
|
||||
|
||||
//Triangles. Data Points point to the Vertex Indices, not the vertices themself. 3 Points = 1 Triangle, Local to View 0
|
||||
if(M2MTriangles.size()>0)
|
||||
M2MTriangles.clear();
|
||||
|
||||
u16 tempM2Triangle;
|
||||
SkinFile->seek(currentView.ofsTris);
|
||||
for(u32 i =0;i<currentView.nTris;i++)
|
||||
{
|
||||
SkinFile->read(&tempM2Triangle,sizeof(u16));
|
||||
M2MTriangles.push_back(tempM2Triangle);
|
||||
}
|
||||
DEBUG(logdebug("Read %u/%u Triangles",M2MTriangles.size(),currentView.nTris));
|
||||
//Submeshes, Local to View 0
|
||||
if(M2MSubmeshes.size()>0)
|
||||
M2MSubmeshes.clear();
|
||||
|
||||
ModelViewSubmesh tempM2Submesh;
|
||||
SkinFile->seek(currentView.ofsSub);
|
||||
for(u32 i =0;i<currentView.nSub;i++)
|
||||
{
|
||||
SkinFile->read(&tempM2Submesh,sizeof(ModelViewSubmesh));
|
||||
M2MSubmeshes.push_back(tempM2Submesh);
|
||||
// std::cout<< "Submesh " <<i<<" ID "<<tempM2Submesh.meshpartId<<" starts at V/T "<<tempM2Submesh.ofsVertex<<"/"<<tempM2Submesh.ofsTris<<" and has "<<tempM2Submesh.nVertex<<"/"<<tempM2Submesh.nTris<<" V/T\n";
|
||||
}
|
||||
DEBUG(logdebug("Read %u/%u Submeshes",M2MSubmeshes.size(),currentView.nSub));
|
||||
|
||||
//Texture units. Local to view 0
|
||||
TextureUnit tempM2TexUnit;
|
||||
if(!M2MTextureUnit.empty())
|
||||
{
|
||||
M2MTextureUnit.clear();
|
||||
}
|
||||
SkinFile->seek(currentView.ofsTex);
|
||||
for(u32 i=0;i<currentView.nTex;i++)
|
||||
{
|
||||
SkinFile->read(&tempM2TexUnit,sizeof(TextureUnit));
|
||||
M2MTextureUnit.push_back(tempM2TexUnit);
|
||||
DEBUG(logdebug(" TexUnit %u: Submesh: %u %u Render Flag: %u TextureUnitNumber: %u %u TTU: %u",i,tempM2TexUnit.submeshIndex1,tempM2TexUnit.submeshIndex2, tempM2TexUnit.renderFlagsIndex, tempM2TexUnit.TextureUnitNumber, tempM2TexUnit.TextureUnitNumber2 ,tempM2TexUnit.textureIndex));
|
||||
}
|
||||
DEBUG(logdebug("Read %u Texture Unit entries for View 0",M2MTextureUnit.size()));
|
||||
// std::string SkinName = MeshFile->getFileName();
|
||||
// SkinName = SkinName.substr(0, SkinName.length()-3) + "00.skin"; // FIX ME (and stuffextract) ! as we need more skins
|
||||
// io::IReadFile* SkinFile = io::IrrCreateIReadFileBasic(Device, SkinName.c_str());
|
||||
// if (!SkinFile)
|
||||
// {
|
||||
// logerror("Error! Skin file not found: %s", SkinName.c_str());
|
||||
// return 0;
|
||||
// }
|
||||
//
|
||||
// SkinFile->read(¤tView, sizeof(ModelView));
|
||||
//
|
||||
// //std::cout << "Skins "<<header.nViews<<" (views)\n";
|
||||
//
|
||||
// DEBUG(logdebug("Using View 0 for all further operations"));
|
||||
// DEBUG(logdebug("This View has %u Submeshes",currentView.nSub));
|
||||
//
|
||||
// //Vertex indices of a specific view.Local to View 0
|
||||
// if(M2MIndices.size()>0)
|
||||
// M2MIndices.clear();
|
||||
//
|
||||
// u16 tempM2Index;
|
||||
// SkinFile->seek(currentView.ofsIndex);
|
||||
// for(u32 i =0;i<currentView.nIndex;i++)
|
||||
// {
|
||||
// SkinFile->read(&tempM2Index,sizeof(u16));
|
||||
// M2MIndices.push_back(tempM2Index);
|
||||
// }
|
||||
// DEBUG(logdebug("Read %u/%u Indices",M2MIndices.size(),currentView.nIndex));
|
||||
//
|
||||
//
|
||||
// //Triangles. Data Points point to the Vertex Indices, not the vertices themself. 3 Points = 1 Triangle, Local to View 0
|
||||
// if(M2MTriangles.size()>0)
|
||||
// M2MTriangles.clear();
|
||||
//
|
||||
// u16 tempM2Triangle;
|
||||
// SkinFile->seek(currentView.ofsTris);
|
||||
// for(u32 i =0;i<currentView.nTris;i++)
|
||||
// {
|
||||
// SkinFile->read(&tempM2Triangle,sizeof(u16));
|
||||
// M2MTriangles.push_back(tempM2Triangle);
|
||||
// }
|
||||
// DEBUG(logdebug("Read %u/%u Triangles",M2MTriangles.size(),currentView.nTris));
|
||||
// //Submeshes, Local to View 0
|
||||
// if(M2MSubmeshes.size()>0)
|
||||
// M2MSubmeshes.clear();
|
||||
//
|
||||
// ModelViewSubmesh tempM2Submesh;
|
||||
// SkinFile->seek(currentView.ofsSub);
|
||||
// for(u32 i =0;i<currentView.nSub;i++)
|
||||
// {
|
||||
// SkinFile->read(&tempM2Submesh,sizeof(ModelViewSubmesh));
|
||||
// M2MSubmeshes.push_back(tempM2Submesh);
|
||||
// // std::cout<< "Submesh " <<i<<" ID "<<tempM2Submesh.meshpartId<<" starts at V/T "<<tempM2Submesh.ofsVertex<<"/"<<tempM2Submesh.ofsTris<<" and has "<<tempM2Submesh.nVertex<<"/"<<tempM2Submesh.nTris<<" V/T\n";
|
||||
// }
|
||||
// DEBUG(logdebug("Read %u/%u Submeshes",M2MSubmeshes.size(),currentView.nSub));
|
||||
//
|
||||
// //Texture units. Local to view 0
|
||||
// TextureUnit tempM2TexUnit;
|
||||
// if(!M2MTextureUnit.empty())
|
||||
// {
|
||||
// M2MTextureUnit.clear();
|
||||
// }
|
||||
// SkinFile->seek(currentView.ofsTex);
|
||||
// for(u32 i=0;i<currentView.nTex;i++)
|
||||
// {
|
||||
// SkinFile->read(&tempM2TexUnit,sizeof(TextureUnit));
|
||||
// M2MTextureUnit.push_back(tempM2TexUnit);
|
||||
// DEBUG(logdebug(" TexUnit %u: Submesh: %u %u Render Flag: %u TextureUnitNumber: %u %u TTU: %u",i,tempM2TexUnit.submeshIndex1,tempM2TexUnit.submeshIndex2, tempM2TexUnit.renderFlagsIndex, tempM2TexUnit.TextureUnitNumber, tempM2TexUnit.TextureUnitNumber2 ,tempM2TexUnit.textureIndex));
|
||||
// }
|
||||
// DEBUG(logdebug("Read %u Texture Unit entries for View 0",M2MTextureUnit.size()));
|
||||
//
|
||||
|
||||
|
||||
|
||||
|
||||
//Texture Lookup table. This is global data
|
||||
u16 tempM2TexLookup;
|
||||
if(!M2MTextureLookup.empty())
|
||||
{
|
||||
M2MTextureLookup.clear();
|
||||
}
|
||||
MeshFile->seek(header.ofsTexLookup);
|
||||
for(u32 i=0;i<header.nTexLookup;i++)
|
||||
{
|
||||
MeshFile->read(&tempM2TexLookup,sizeof(u16));
|
||||
M2MTextureLookup.push_back(tempM2TexLookup);
|
||||
DEBUG(logdebug("Texture %u Type %u\n",i,tempM2TexLookup));
|
||||
}
|
||||
DEBUG(logdebug("Read %u Texture lookup entries",M2MTextureLookup.size()));
|
||||
|
||||
//Texture Definitions table. This is global data
|
||||
TextureDefinition tempM2TexDef;
|
||||
if(!M2MTextureDef.empty())
|
||||
{
|
||||
M2MTextureDef.clear();
|
||||
}
|
||||
MeshFile->seek(header.ofsTextures);
|
||||
for(u32 i=0;i<header.nTextures;i++)
|
||||
{
|
||||
MeshFile->read(&tempM2TexDef,sizeof(TextureDefinition));
|
||||
M2MTextureDef.push_back(tempM2TexDef);
|
||||
DEBUG(logdebug("Texture %u Type %u\n",i,tempM2TexDef.texType));
|
||||
}
|
||||
DEBUG(logdebug("Read %u Texture Definition entries",M2MTextureDef.size()));
|
||||
|
||||
//Render Flags table. This is global data
|
||||
RenderFlags tempM2RF;
|
||||
if(!M2MRenderFlags.empty())
|
||||
{
|
||||
M2MRenderFlags.clear();
|
||||
}
|
||||
MeshFile->seek(header.ofsTexFlags);
|
||||
for(u32 i=0;i<header.nTexFlags;i++)
|
||||
{
|
||||
MeshFile->read(&tempM2RF,sizeof(RenderFlags));
|
||||
M2MRenderFlags.push_back(tempM2RF);
|
||||
DEBUG(logdebug("Flag %u: (%u, %u)",i,tempM2RF.blending,tempM2RF.flags));
|
||||
}
|
||||
DEBUG(logdebug("Read %u Renderflags",M2MRenderFlags.size()));
|
||||
|
||||
if(!M2MTextureFiles.empty())
|
||||
M2MTextureFiles.clear();
|
||||
|
||||
std::string tempTexFileName="";
|
||||
M2MTextureFiles.reallocate(M2MTextureDef.size());
|
||||
for(u32 i=0; i<M2MTextureDef.size(); i++)
|
||||
{
|
||||
tempTexFileName.resize(M2MTextureDef[i].texFileLen + 1);
|
||||
MeshFile->seek(M2MTextureDef[i].texFileOfs);
|
||||
MeshFile->read((void*)tempTexFileName.data(),M2MTextureDef[i].texFileLen);
|
||||
M2MTextureFiles.push_back("");
|
||||
M2MTextureFiles[i]=tempTexFileName.c_str();
|
||||
DEBUG(logdebug("Texture: %u %u (%s/%s) @ %u(%u)",i,M2MTextureFiles.size(),M2MTextureFiles[i].c_str(),tempTexFileName.c_str(),M2MTextureDef[i].texFileOfs,M2MTextureDef[i].texFileLen));
|
||||
}
|
||||
|
||||
///////////////////////////////////////
|
||||
// Animation related stuff //
|
||||
@ -440,6 +542,19 @@ if(M2MBones[i].scaling.header.nValues>0){
|
||||
}
|
||||
*/
|
||||
//std::cout<<AnimatedMesh->getAllJoints()[1]->Children.size()<<" Children\n";
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////
|
||||
// EVERYTHING IS READ
|
||||
///////////////////////////
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//And M2MVertices are not usable like this. Thus we transform
|
||||
|
||||
if(M2Vertices.size()>0)
|
||||
@ -468,8 +583,8 @@ for(u32 i=0; i < currentView.nSub;i++)//
|
||||
for(u32 j=M2MSubmeshes[i].ofsVertex;j<M2MSubmeshes[i].ofsVertex+M2MSubmeshes[i].nVertex;j++)
|
||||
{
|
||||
MeshBuffer->Vertices_Standard.push_back(M2Vertices[j]);
|
||||
for(u32 k=0; k<4; k++)
|
||||
{
|
||||
// for(u32 k=0; k<4; k++)
|
||||
// {
|
||||
//std::cout << (u32)M2MVertices[j].bones[k] << " ";
|
||||
/* ANIMATION NEED FIX !!!
|
||||
if((M2MVertices[j].weights[k]/255.0f)>0.0f)
|
||||
@ -481,7 +596,7 @@ for(u32 i=0; i < currentView.nSub;i++)//
|
||||
}
|
||||
*/
|
||||
//std::cout<<weight->buffer_id << " " << weight->vertex_id << " " << weight->strength <<"|";
|
||||
}
|
||||
// }
|
||||
// std::cout<<'\n';
|
||||
}
|
||||
//std::cout << i << ": " << MeshBuffer->Vertices_Standard.size() <<" "<<M2MSubmeshes[i].ofsVertex<<" "<<M2MSubmeshes[i].nVertex<< "\n";
|
||||
@ -491,10 +606,10 @@ for(u32 i=0; i < currentView.nSub;i++)//
|
||||
//MeshBuffer->getMaterial().DiffuseColor.set(255,255-(u32)(255/(M2MSubmeshes.size()))*i,(u32)(255/(M2MSubmeshes.size()))*i,0);
|
||||
//MeshBuffer->getMaterial().DiffuseColor.set(255,(M2MSubmeshes[i].meshpartId==0?0:255),(M2MSubmeshes[i].meshpartId==0?255:0),0);
|
||||
for(u32 j=0;j<M2MTextureUnit.size();j++)//Loop through texture units
|
||||
{
|
||||
{
|
||||
if(M2MTextureUnit[j].submeshIndex1==i && !M2MTextureFiles[M2MTextureLookup[M2MTextureUnit[j].textureIndex]].empty())//if a texture unit belongs to this submesh
|
||||
{
|
||||
// std::string TexName=Texdir.c_str();
|
||||
{
|
||||
// std::string TexName=Texdir.c_str();
|
||||
// TexName+="/";
|
||||
// if(i<M2MTextureUnit.size())
|
||||
// TexName+=M2MTextureFiles[M2MTextureLookup[M2MTextureUnit[j].textureIndex]].c_str();
|
||||
@ -509,26 +624,33 @@ for(u32 i=0; i < currentView.nSub;i++)//
|
||||
std::transform(TexName.begin(), TexName.end(), TexName.begin(), tolower);*/
|
||||
char buf[1000];
|
||||
MemoryDataHolder::MakeTextureFilename(buf,M2MTextureFiles[M2MTextureLookup[M2MTextureUnit[j].textureIndex]].c_str());
|
||||
io::IReadFile* TexFile = io::IrrCreateIReadFileBasic(Device, buf);
|
||||
// logdebug("Texture %s loading",M2MTextureFiles[M2MTextureLookup[M2MTextureUnit[j].textureIndex]].c_str());
|
||||
if (!TexFile)
|
||||
video::ITexture* tex = Device->getVideoDriver()->findTexture(buf);
|
||||
if(!tex)
|
||||
{
|
||||
logerror("CM2MeshFileLoader: Texture file not found: %s", buf);
|
||||
continue;
|
||||
}
|
||||
io::IReadFile* TexFile = io::IrrCreateIReadFileBasic(Device, buf);
|
||||
// logdebug("Texture %s loading",M2MTextureFiles[M2MTextureLookup[M2MTextureUnit[j].textureIndex]].c_str());
|
||||
if (!TexFile)
|
||||
{
|
||||
logerror("CM2MeshFileLoader: Texture file not found: %s", buf);
|
||||
continue;
|
||||
}
|
||||
// logdebug("Texture %s loaded",M2MTextureFiles[M2MTextureLookup[M2MTextureUnit[j].textureIndex]].c_str());
|
||||
MeshBuffer->getMaterial().setTexture(M2MTextureUnit[j].TextureUnitNumber,Device->getVideoDriver()->getTexture(TexFile));
|
||||
|
||||
tex = Device->getVideoDriver()->getTexture(TexFile);
|
||||
TexFile->drop();
|
||||
}
|
||||
MeshBuffer->getMaterial().setTexture(M2MTextureUnit[j].TextureUnitNumber,tex);
|
||||
|
||||
DEBUG(logdebug("Render Flags: %u %u",M2MRenderFlags[M2MTextureUnit[j].renderFlagsIndex].flags,M2MRenderFlags[M2MTextureUnit[j].renderFlagsIndex].blending));
|
||||
MeshBuffer->getMaterial().BackfaceCulling=(M2MRenderFlags[M2MTextureUnit[j].renderFlagsIndex].flags & 0x04)?false:true;
|
||||
if(M2MRenderFlags[M2MTextureUnit[j].renderFlagsIndex].blending==1)
|
||||
MeshBuffer->getMaterial().MaterialType=video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
MeshBuffer->recalculateBoundingBox();
|
||||
MeshBuffer->setHardwareMappingHint(EHM_STATIC);
|
||||
|
||||
//MeshBuffer->recalculateBoundingBox();
|
||||
// Mesh->addMeshBuffer(MeshBuffer);
|
||||
// Mesh->recalculateBoundingBox();
|
||||
//MeshBuffer->drop();
|
||||
@ -546,7 +668,7 @@ Device->getSceneManager()->getMeshManipulator()->flipSurfaces(AnimatedMesh); //F
|
||||
|
||||
AnimatedMesh->setInterpolationMode(scene::EIM_LINEAR);
|
||||
|
||||
SkinFile->drop();
|
||||
// SkinFile->drop();
|
||||
M2MTriangles.clear();
|
||||
M2Vertices.clear();
|
||||
M2Indices.clear();
|
||||
|
||||
@ -11,80 +11,86 @@ namespace scene
|
||||
{
|
||||
|
||||
struct ModelHeader {
|
||||
c8 id[4];
|
||||
u8 version[4];
|
||||
c8 id[4]; //0x00
|
||||
u32 version;
|
||||
u32 nameLength;
|
||||
u32 nameOfs;
|
||||
u32 type;
|
||||
u32 nameOfs;
|
||||
u32 type; //0x10
|
||||
|
||||
//Anim Block @ 0x14
|
||||
u32 nGlobalSequences;
|
||||
u32 ofsGlobalSequences;
|
||||
u32 nAnimations;
|
||||
u32 ofsAnimations;
|
||||
u32 nC;
|
||||
u32 ofsC;
|
||||
u32 ofsAnimations; //0x20
|
||||
u32 nAnimationLookup;
|
||||
u32 ofsAnimationLookup;
|
||||
u32 nD;
|
||||
u32 ofsD; //0x30
|
||||
u32 nBones;
|
||||
u32 ofsBones;
|
||||
u32 nF;
|
||||
u32 ofsF;
|
||||
u32 nSkelBoneLookup;
|
||||
u32 ofsSkelBoneLookup; //0x40
|
||||
|
||||
u32 nVertices;
|
||||
u32 nVertices; //0x44
|
||||
u32 ofsVertices;
|
||||
u32 nViews; // number of skins ?
|
||||
u32 ofsViews; //0x50
|
||||
|
||||
u32 nColors;
|
||||
u32 ofsColors;
|
||||
|
||||
u32 nTextures;
|
||||
u32 ofsTextures;
|
||||
u32 ofsTextures; //0x60
|
||||
|
||||
u32 nTransparency; // H
|
||||
u32 nTransparency;
|
||||
u32 ofsTransparency;
|
||||
u32 nTexAnims; // J
|
||||
u32 nI;
|
||||
u32 ofsI; //0x70
|
||||
u32 nTexAnims;
|
||||
u32 ofsTexAnims;
|
||||
u32 nTexReplace;
|
||||
u32 ofsTexReplace;
|
||||
u32 ofsTexReplace; //0x80
|
||||
|
||||
u32 nTexFlags;
|
||||
u32 ofsTexFlags;
|
||||
u32 nY;
|
||||
u32 ofsY;
|
||||
u32 ofsY; //0x90
|
||||
|
||||
u32 nTexLookup;
|
||||
u32 ofsTexLookup;
|
||||
|
||||
u32 nTexUnitLookup; // L
|
||||
u32 ofsTexUnitLookup;
|
||||
u32 nTransparencyLookup; // M
|
||||
u32 nTexUnitLookup;
|
||||
u32 ofsTexUnitLookup; //0xa0
|
||||
u32 nTransparencyLookup;
|
||||
u32 ofsTransparencyLookup;
|
||||
u32 nTexAnimLookup;
|
||||
u32 ofsTexAnimLookup;
|
||||
u32 ofsTexAnimLookup; //0xb0
|
||||
|
||||
f32 floats[14];
|
||||
|
||||
u32 nBoundingTriangles;
|
||||
u32 ofsBoundingTriangles;
|
||||
u32 nBoundingTriangles;
|
||||
u32 ofsBoundingTriangles; //0xf0
|
||||
u32 nBoundingVertices;
|
||||
u32 ofsBoundingVertices;
|
||||
u32 nBoundingNormals;
|
||||
u32 ofsBoundingNormals;
|
||||
u32 ofsBoundingNormals; //0x100
|
||||
|
||||
u32 nAttachments; // O
|
||||
u32 nAttachments;
|
||||
u32 ofsAttachments;
|
||||
u32 nAttachLookup; // P
|
||||
u32 ofsAttachLookup;
|
||||
u32 nQ; // Q
|
||||
u32 ofsQ;
|
||||
u32 nLights; // R
|
||||
u32 ofsLights;
|
||||
u32 nCameras; // S
|
||||
u32 nAttachLookup;
|
||||
u32 ofsAttachLookup; //0x110
|
||||
u32 nAttachments_2;
|
||||
u32 ofsAttachments_2;
|
||||
u32 nLights;
|
||||
u32 ofsLights; //0x120
|
||||
u32 nCameras;
|
||||
u32 ofsCameras;
|
||||
u32 nT;
|
||||
u32 ofsT;
|
||||
u32 nRibbonEmitters; // U
|
||||
u32 nCameraLookup;
|
||||
u32 ofsnCameraLookup; //0x130
|
||||
u32 nRibbonEmitters;
|
||||
u32 ofsRibbonEmitters;
|
||||
u32 nParticleEmitters; // V
|
||||
u32 ofsParticleEmitters;
|
||||
u32 nParticleEmitters;
|
||||
u32 ofsParticleEmitters;//0x140
|
||||
|
||||
};
|
||||
|
||||
@ -106,13 +112,13 @@ struct ModelVertex {
|
||||
};
|
||||
|
||||
struct ModelView {
|
||||
c8 id[4]; // always "SKIN"
|
||||
// c8 id[4]; // always "SKIN"
|
||||
u32 nIndex, ofsIndex; // Vertices in this model (index into vertices[])
|
||||
u32 nTris, ofsTris; // indices
|
||||
u32 nProps, ofsProps; // additional vtx properties
|
||||
u32 nSub, ofsSub; // materials/renderops/submeshes
|
||||
u32 nTex, ofsTex; // material properties/textures
|
||||
s32 lod; // LOD bias?
|
||||
u32 lod; // LOD bias?
|
||||
};
|
||||
|
||||
struct ModelViewSubmesh {
|
||||
@ -212,17 +218,21 @@ public:
|
||||
private:
|
||||
|
||||
bool load();
|
||||
void ReadVertices();
|
||||
void ReadTextureDefinitions();
|
||||
void ReadViewData(io::IReadFile* file);
|
||||
|
||||
IrrlichtDevice* Device;
|
||||
IrrlichtDevice *Device;
|
||||
core::stringc Texdir;
|
||||
io::IReadFile* MeshFile;
|
||||
io::IReadFile *MeshFile, *SkinFile;
|
||||
|
||||
CSkinnedMesh* AnimatedMesh;
|
||||
scene::CSkinnedMesh::SJoint* ParentJoint;
|
||||
CSkinnedMesh *AnimatedMesh;
|
||||
scene::CSkinnedMesh::SJoint *ParentJoint;
|
||||
|
||||
|
||||
|
||||
ModelHeader header;
|
||||
ModelView currentView;
|
||||
core::stringc M2MeshName;
|
||||
SMesh* Mesh;
|
||||
//SSkinMeshBuffer* MeshBuffer;
|
||||
|
||||
@ -26,9 +26,8 @@ CMDHReadFile::CMDHReadFile(void* memory, long len, const c8* fileName)
|
||||
|
||||
CMDHReadFile::~CMDHReadFile()
|
||||
{
|
||||
// We should not drop the memory here... this model will possibly be loaded more than once
|
||||
//if(getReferenceCount() <= 1)
|
||||
// MemoryDataHolder::Delete(getFileName());
|
||||
// Drop the Memory, Irrlicht keeps a Model Cache of loaded models
|
||||
MemoryDataHolder::Delete(getFileName());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -60,7 +60,7 @@ IAnimatedMesh* CWMOMeshFileLoader::createMesh(io::IReadFile* file)
|
||||
{
|
||||
char grpfilename[255];
|
||||
sprintf(grpfilename,"%s_%03u.wmo",filename.substr(0,filename.length()-4).c_str(),i);
|
||||
logdev("%s",grpfilename);
|
||||
DEBUG(logdev("%s",grpfilename));
|
||||
MeshFile = io::IrrCreateIReadFileBasic(Device,grpfilename);
|
||||
if(!MeshFile)
|
||||
{
|
||||
@ -73,7 +73,7 @@ IAnimatedMesh* CWMOMeshFileLoader::createMesh(io::IReadFile* file)
|
||||
Device->getSceneManager()->getMeshManipulator()->flipSurfaces(Mesh); //Fix inverted surfaces after the rotation
|
||||
//Does this crash on windows?
|
||||
Device->getSceneManager()->getMeshManipulator()->recalculateNormals(Mesh,true);//just to be sure
|
||||
logdev("Complete Mesh contains a total of %u submeshes!",Mesh->getMeshBufferCount());
|
||||
DEBUG(logdev("Complete Mesh contains a total of %u submeshes!",Mesh->getMeshBufferCount()));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -92,24 +92,24 @@ bool CWMOMeshFileLoader::load(bool _root)
|
||||
u32 size;
|
||||
u32 textureOffset;
|
||||
|
||||
logdev("Trying to open file %s",MeshFile->getFileName());
|
||||
DEBUG(logdev("Trying to open file %s",MeshFile->getFileName()));
|
||||
|
||||
while(MeshFile->getPos() < MeshFile->getSize())
|
||||
{
|
||||
MeshFile->read(fourcc,4);
|
||||
MeshFile->read(&size,4);
|
||||
flipcc(fourcc);
|
||||
logdev("Reading Chunk: %s size %u", (char*)fourcc,size);
|
||||
DEBUG(logdev("Reading Chunk: %s size %u", (char*)fourcc,size));
|
||||
|
||||
if(!strcmp((char*)fourcc,"MVER")){
|
||||
logdev("MVER Chunk: %s",(char*)fourcc);
|
||||
DEBUG(logdev("MVER Chunk: %s",(char*)fourcc));
|
||||
MeshFile->seek(size,true);
|
||||
}
|
||||
|
||||
//Start root file parsing
|
||||
else if(!strcmp((char*)fourcc,"MOHD")){
|
||||
MeshFile->read(&rootHeader,sizeof(RootHeader));
|
||||
logdev("Read Root Header: %u Textures, %u Groups, %u Models", rootHeader.nTextures, rootHeader.nGroups, rootHeader.nModels);
|
||||
DEBUG(logdev("Read Root Header: %u Textures, %u Groups, %u Models", rootHeader.nTextures, rootHeader.nGroups, rootHeader.nModels));
|
||||
if(!isRootFile)//We should be reading a group file and found a root header, abort
|
||||
return 0;
|
||||
}
|
||||
@ -127,7 +127,7 @@ logdev("Reading Chunk: %s size %u", (char*)fourcc,size);
|
||||
MeshFile->read(&tempMOMT,sizeof(MOMT_Data));
|
||||
WMOMTexDefinition.push_back(tempMOMT);
|
||||
}
|
||||
logdev("Read %u/%u TextureDefinitions",WMOMTexDefinition.size(),(size/sizeof(MOMT_Data)));
|
||||
DEBUG(logdev("Read %u/%u TextureDefinitions",WMOMTexDefinition.size(),(size/sizeof(MOMT_Data))));
|
||||
|
||||
u32 tempOffset = MeshFile->getPos();//Save current position for further reading until texture file names are read.
|
||||
|
||||
@ -141,7 +141,7 @@ logdev("Reading Chunk: %s size %u", (char*)fourcc,size);
|
||||
texNameSize = WMOMTexDefinition[i].endNameIndex-WMOMTexDefinition[i].startNameIndex; tempTexName.resize(texNameSize);
|
||||
MeshFile->seek(textureOffset+WMOMTexDefinition[i].startNameIndex);
|
||||
MeshFile->read((void*)tempTexName.c_str(),WMOMTexDefinition[i].endNameIndex-WMOMTexDefinition[i].startNameIndex);
|
||||
logdev("Texture %u: %s",i,tempTexName.c_str());
|
||||
DEBUG(logdev("Texture %u: %s",i,tempTexName.c_str()));
|
||||
WMOMTextureFiles.push_back(tempTexName.c_str());
|
||||
}
|
||||
|
||||
@ -152,7 +152,7 @@ logdev("Reading Chunk: %s size %u", (char*)fourcc,size);
|
||||
|
||||
//Start Group file parsing
|
||||
else if(!strcmp((char*)fourcc,"MOGP")){
|
||||
logdev("header okay: %s",(char*)fourcc);
|
||||
DEBUG(logdev("header okay: %s",(char*)fourcc));
|
||||
MeshFile->seek(68,true);
|
||||
if(isRootFile)//We should be reading a root file and found a Group header, abort
|
||||
return 0;
|
||||
@ -174,7 +174,7 @@ logdev("Reading Chunk: %s size %u", (char*)fourcc,size);
|
||||
previous_texid=tempMOPY.textureID;
|
||||
}
|
||||
submeshes.push_back(WMOMTexData.size()-1);//last read entry
|
||||
logdev("Read %u/%u Texture Informations, counted %u submeshes",WMOMTexData.size(),(size/sizeof(MOPY_Data)),submeshes.size());
|
||||
DEBUG(logdev("Read %u/%u Texture Informations, counted %u submeshes",WMOMTexData.size(),(size/sizeof(MOPY_Data)),submeshes.size()));
|
||||
|
||||
}
|
||||
else if(!strcmp((char*)fourcc,"MOVI")){//Vertex indices (3 per triangle)
|
||||
@ -187,7 +187,7 @@ logdev("Reading Chunk: %s size %u", (char*)fourcc,size);
|
||||
MeshFile->read(&tempWMOIndex,sizeof(u16));
|
||||
WMOMIndices.push_back(tempWMOIndex);
|
||||
}
|
||||
logdev("Read %u/%u Indices",WMOMIndices.size(),(size/sizeof(u16)));
|
||||
DEBUG(logdev("Read %u/%u Indices",WMOMIndices.size(),(size/sizeof(u16))));
|
||||
|
||||
}
|
||||
else if(!strcmp((char*)fourcc,"MOVT")){//Vertex coordinates
|
||||
@ -204,7 +204,7 @@ logdev("Reading Chunk: %s size %u", (char*)fourcc,size);
|
||||
tempWMOVertex.Z=tempYZ;
|
||||
WMOMVertices.push_back(tempWMOVertex);
|
||||
}
|
||||
logdev("Read %u/%u Vertex Coordinates",WMOMVertices.size(),(size/sizeof(core::vector3df)));
|
||||
DEBUG(logdev("Read %u/%u Vertex Coordinates",WMOMVertices.size(),(size/sizeof(core::vector3df))));
|
||||
|
||||
}
|
||||
else if(!strcmp((char*)fourcc,"MONR")){//Normals
|
||||
@ -221,7 +221,7 @@ logdev("Reading Chunk: %s size %u", (char*)fourcc,size);
|
||||
tempWMONormal.Z=tempYZ;
|
||||
WMOMNormals.push_back(tempWMONormal);
|
||||
}
|
||||
logdev("Read %u/%u Normal Coordinates",WMOMNormals.size(),(size/sizeof(core::vector3df)));
|
||||
DEBUG(logdev("Read %u/%u Normal Coordinates",WMOMNormals.size(),(size/sizeof(core::vector3df))));
|
||||
|
||||
}
|
||||
else if(!strcmp((char*)fourcc,"MOTV")){//TexCoord
|
||||
@ -234,7 +234,7 @@ logdev("Reading Chunk: %s size %u", (char*)fourcc,size);
|
||||
MeshFile->read(&tempWMOMTexcoord,sizeof(core::vector2df));
|
||||
WMOMTexcoord.push_back(tempWMOMTexcoord);
|
||||
}
|
||||
logdev("Read %u/%u Texture Coordinates",WMOMTexcoord.size(),(size/sizeof(core::vector2df)));
|
||||
DEBUG(logdev("Read %u/%u Texture Coordinates",WMOMTexcoord.size(),(size/sizeof(core::vector2df))));
|
||||
|
||||
}
|
||||
else if(!strcmp((char*)fourcc,"MOCV")){//Vertex colors!! Scaaaary!
|
||||
@ -248,7 +248,7 @@ logdev("Reading Chunk: %s size %u", (char*)fourcc,size);
|
||||
MeshFile->read(&tempWMOMVertexColor,sizeof(WMOColor));
|
||||
WMOMVertexColor.push_back(video::SColor(tempWMOMVertexColor.a,tempWMOMVertexColor.r,tempWMOMVertexColor.g,tempWMOMVertexColor.b));
|
||||
}
|
||||
logdev("Read %u/%u Vertex colors",WMOMVertexColor.size(),(size/sizeof(WMOColor)));
|
||||
DEBUG(logdev("Read %u/%u Vertex colors",WMOMVertexColor.size(),(size/sizeof(WMOColor))));
|
||||
|
||||
}
|
||||
//End Group file parsing
|
||||
@ -287,14 +287,14 @@ for(u32 i=0;i<submeshes.size();i++)//The mesh has to be split into submeshes bec
|
||||
MeshBuffer->Indices.push_back(WMOMIndices[j*3+2]);
|
||||
}
|
||||
}
|
||||
logdev("Inserted %u Indices",MeshBuffer->Indices.size());
|
||||
DEBUG(logdev("Inserted %u Indices",MeshBuffer->Indices.size()));
|
||||
|
||||
for(u32 j=0;j<WMOVertices.size();j++)
|
||||
{
|
||||
MeshBuffer->Vertices_Standard.push_back(WMOVertices[j]);
|
||||
}
|
||||
|
||||
logdev("Inserted %u Vertices",MeshBuffer->Vertices_Standard.size());
|
||||
DEBUG(logdev("Inserted %u Vertices",MeshBuffer->Vertices_Standard.size()));
|
||||
|
||||
// std::string TexName=Texdir.c_str();
|
||||
// TexName+="/";
|
||||
@ -310,17 +310,26 @@ for(u32 i=0;i<submeshes.size();i++)//The mesh has to be split into submeshes bec
|
||||
// std::transform(TexName.begin(), TexName.end(), TexName.begin(), tolower);
|
||||
char buf[1000];
|
||||
MemoryDataHolder::MakeTextureFilename(buf,WMOMTextureFiles[WMOMTexData[lastindex].textureID].c_str());
|
||||
io::IReadFile* TexFile = io::IrrCreateIReadFileBasic(Device, buf);
|
||||
if (!TexFile)
|
||||
video::ITexture* tex = Device->getVideoDriver()->findTexture(buf);
|
||||
if(!tex)
|
||||
{
|
||||
logerror("Error! Texture file not found: %s", buf);
|
||||
continue;
|
||||
io::IReadFile* TexFile = io::IrrCreateIReadFileBasic(Device, buf);
|
||||
// logdebug("Texture %s loading",M2MTextureFiles[M2MTextureLookup[M2MTextureUnit[j].textureIndex]].c_str());
|
||||
if (!TexFile)
|
||||
{
|
||||
logerror("CM2MeshFileLoader: Texture file not found: %s", buf);
|
||||
continue;
|
||||
}
|
||||
// logdebug("Texture %s loaded",M2MTextureFiles[M2MTextureLookup[M2MTextureUnit[j].textureIndex]].c_str());
|
||||
tex = Device->getVideoDriver()->getTexture(TexFile);
|
||||
TexFile->drop();
|
||||
}
|
||||
|
||||
MeshBuffer->getMaterial().setTexture(0,Device->getVideoDriver()->getTexture(TexFile));
|
||||
MeshBuffer->getMaterial().setTexture(0,tex);
|
||||
if(WMOMTexDefinition[WMOMTexData[lastindex].textureID].blendMode==1)
|
||||
MeshBuffer->getMaterial().MaterialType=video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
||||
MeshBuffer->recalculateBoundingBox();
|
||||
MeshBuffer->setHardwareMappingHint(EHM_STATIC);
|
||||
}
|
||||
lastindex=submeshes[i];
|
||||
|
||||
|
||||
@ -628,22 +628,29 @@ void SceneWorld::UpdateTerrain(void)
|
||||
if(_doodads.find(d->uniqueid) == _doodads.end()) // only add doodads that dont exist yet
|
||||
{
|
||||
std::string filename;
|
||||
if(instance->GetConf()->useMPQ)
|
||||
|
||||
filename= d->model.c_str();//This is a hack and needs fixing at some point.
|
||||
//Actually the point at which this will be fixed is when all art assets are loaded together
|
||||
//because there is no point in loading them separately
|
||||
|
||||
// logdebug("loading Doodad %s",filename.c_str());
|
||||
scene::IAnimatedMesh *mesh;
|
||||
if(!smgr->getMeshCache()->isMeshLoaded(filename.c_str()))
|
||||
{
|
||||
filename= d->MPQpath.c_str();
|
||||
io::IReadFile* modelfile = io::IrrCreateIReadFileBasic(device, filename.c_str());
|
||||
if (!modelfile)
|
||||
{
|
||||
logerror("Error! modelfile not found: %s", filename.c_str());
|
||||
continue;
|
||||
}
|
||||
mesh = smgr->getMesh(modelfile);
|
||||
modelfile->drop();
|
||||
}
|
||||
else
|
||||
{
|
||||
filename= d->model.c_str();
|
||||
mesh = smgr->getMeshCache()->getMeshByFilename(filename.c_str());
|
||||
}
|
||||
// logdebug("loading Doodad %s",filename.c_str());
|
||||
io::IReadFile* modelfile = io::IrrCreateIReadFileBasic(device, filename.c_str());
|
||||
if (!modelfile)
|
||||
{
|
||||
logerror("Error! modelfile not found: %s", d->MPQpath.c_str());
|
||||
continue;
|
||||
}
|
||||
scene::IAnimatedMesh *mesh = smgr->getMesh(modelfile);
|
||||
|
||||
if(mesh)
|
||||
{
|
||||
scene::IAnimatedMeshSceneNode *doodad = smgr->addAnimatedMeshSceneNode(mesh);
|
||||
@ -677,6 +684,10 @@ void SceneWorld::UpdateTerrain(void)
|
||||
_doodads[d->uniqueid] = gp;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
logerror("No mesh provided");
|
||||
}
|
||||
}
|
||||
}
|
||||
// create WorldMapObjects (WMOs)
|
||||
@ -695,14 +706,24 @@ void SceneWorld::UpdateTerrain(void)
|
||||
{
|
||||
filename= wmo->model.c_str();
|
||||
}
|
||||
// logdebug("loading WMO %s",filename.c_str());
|
||||
io::IReadFile* modelfile = io::IrrCreateIReadFileBasic(device, filename.c_str());
|
||||
if (!modelfile)
|
||||
{
|
||||
logerror("Error! WMO file not found: %s", wmo->MPQpath.c_str());
|
||||
continue;
|
||||
}
|
||||
scene::IAnimatedMesh *mesh = smgr->getMesh(modelfile);
|
||||
|
||||
scene::IAnimatedMesh *mesh;
|
||||
if(!smgr->getMeshCache()->isMeshLoaded(filename.c_str()))
|
||||
{
|
||||
io::IReadFile* modelfile = io::IrrCreateIReadFileBasic(device, filename.c_str());
|
||||
if (!modelfile)
|
||||
{
|
||||
logerror("Error! modelfile not found: %s", filename.c_str());
|
||||
continue;
|
||||
}
|
||||
mesh = smgr->getMesh(modelfile);
|
||||
modelfile->drop();
|
||||
}
|
||||
else
|
||||
{
|
||||
mesh = smgr->getMeshCache()->getMeshByFilename(filename.c_str());
|
||||
}
|
||||
|
||||
if(mesh)
|
||||
{
|
||||
scene::IAnimatedMeshSceneNode *wmo_node = smgr->addAnimatedMeshSceneNode(mesh);
|
||||
|
||||
@ -87,13 +87,27 @@ namespace MemoryDataHolder
|
||||
}
|
||||
}
|
||||
void MakeModelFilename(char* fn, std::string fname)
|
||||
{
|
||||
if(fname.find(".mdx")!=std::string::npos)
|
||||
fname.replace(fname.length()-3,3,"m2");
|
||||
if(loadFromMPQ)
|
||||
{
|
||||
sprintf(fn,"%s",fname.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
NormalizeFilename(_PathToFileName(fname));
|
||||
sprintf(fn,"./data/model/%s",fname.c_str());
|
||||
}
|
||||
}
|
||||
void MakeWMOFilename(char* fn, std::string fname)
|
||||
{
|
||||
if(loadFromMPQ)
|
||||
sprintf(fn,"%s",fname.c_str());
|
||||
else
|
||||
{
|
||||
NormalizeFilename(_PathToFileName(fname));
|
||||
sprintf(fn,"./data/model/%s",fname.c_str());
|
||||
sprintf(fn,"./data/wmos/%s",fname.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
@ -117,7 +131,7 @@ namespace MemoryDataHolder
|
||||
}
|
||||
~DataLoaderRunnable()
|
||||
{
|
||||
logdev("~DataLoaderRunnable(%s) 0x%X", _name.c_str(), this);
|
||||
DEBUG(logdev("~DataLoaderRunnable(%s) 0x%X", _name.c_str(), this));
|
||||
}
|
||||
void SetStores(TypeStorage<memblock> *mem, TypeStorage<DataLoaderRunnable> *ldrs)
|
||||
{
|
||||
@ -139,7 +153,7 @@ namespace MemoryDataHolder
|
||||
delete mb;
|
||||
return;
|
||||
}
|
||||
logdev("DataLoaderRunnable: Reading From MPQ'%s'... (%s)", _name.c_str(), FilesizeFormat(mb->size).c_str());
|
||||
DEBUG(logdev("DataLoaderRunnable: Reading From MPQ'%s'... (%s)", _name.c_str(), FilesizeFormat(mb->size).c_str()));
|
||||
const ByteBuffer& bb = mpq.ExtractFile(_name.c_str());
|
||||
// fh.read((char*)mb->ptr, mb->size);
|
||||
if(!bb.size())
|
||||
@ -161,7 +175,7 @@ namespace MemoryDataHolder
|
||||
_storage->Assign(_name, mb);
|
||||
_loaders->Unlink(_name); // must be unlinked after the file is fully loaded, but before the callbacks are processed!
|
||||
}
|
||||
logdev("DataLoaderRunnable: Done with '%s' (%s)", _name.c_str(), FilesizeFormat(mb->size).c_str());
|
||||
DEBUG(logdev("DataLoaderRunnable: Done with '%s' (%s)", _name.c_str(), FilesizeFormat(mb->size).c_str()));
|
||||
DoCallbacks(_name, MDH_FILE_OK | MDH_FILE_JUST_LOADED);
|
||||
}
|
||||
else
|
||||
@ -194,7 +208,7 @@ namespace MemoryDataHolder
|
||||
DoCallbacks(_name, MDH_FILE_ERROR);
|
||||
return;
|
||||
}
|
||||
logdev("DataLoaderRunnable: Reading '%s'... (%s)", _name.c_str(), FilesizeFormat(mb->size).c_str());
|
||||
DEBUG(logdev("DataLoaderRunnable: Reading '%s'... (%s)", _name.c_str(), FilesizeFormat(mb->size).c_str()));
|
||||
fh.read((char*)mb->ptr, mb->size);
|
||||
fh.close();
|
||||
{
|
||||
@ -202,7 +216,7 @@ namespace MemoryDataHolder
|
||||
_storage->Assign(_name, mb);
|
||||
_loaders->Unlink(_name); // must be unlinked after the file is fully loaded, but before the callbacks are processed!
|
||||
}
|
||||
logdev("DataLoaderRunnable: Done with '%s' (%s)", _name.c_str(), FilesizeFormat(mb->size).c_str());
|
||||
DEBUG(logdev("DataLoaderRunnable: Done with '%s' (%s)", _name.c_str(), FilesizeFormat(mb->size).c_str()));
|
||||
DoCallbacks(_name, MDH_FILE_OK | MDH_FILE_JUST_LOADED);
|
||||
}
|
||||
}
|
||||
@ -358,14 +372,14 @@ namespace MemoryDataHolder
|
||||
{
|
||||
if(*refcount > 0)
|
||||
(*refcount)--;
|
||||
logdev("MemoryDataHolder::Delete(\"%s\"): refcount dropped to %u", s.c_str(), *refcount);
|
||||
DEBUG(logdev("MemoryDataHolder::Delete(\"%s\"): refcount dropped to %u", s.c_str(), *refcount));
|
||||
}
|
||||
if(!*refcount)
|
||||
{
|
||||
refs.Delete(s);
|
||||
if(memblock *mb = storage.GetNoCreate(s))
|
||||
{
|
||||
logdev("MemoryDataHolder:: deleting 0x%X (size %s)", mb->ptr, FilesizeFormat(mb->size).c_str());
|
||||
DEBUG(logdev("MemoryDataHolder:: deleting 0x%X (size %s)", mb->ptr, FilesizeFormat(mb->size).c_str()));
|
||||
mb->free();
|
||||
storage.Delete(s);
|
||||
return true;
|
||||
|
||||
@ -54,6 +54,7 @@ namespace MemoryDataHolder
|
||||
void MakeWDTFilename(char*,uint32,std::string);
|
||||
void MakeTextureFilename(char*, std::string);
|
||||
void MakeModelFilename(char*, std::string);
|
||||
void MakeWMOFilename(char*, std::string);
|
||||
bool FileExists(std::string);
|
||||
|
||||
MemoryDataResult GetFile(std::string s, bool threaded = false, callback_func func = NULL,void *ptr = NULL, ZThread::Condition *cond = NULL, bool ref_counted = true);
|
||||
|
||||
@ -494,11 +494,6 @@ void PseuInstanceConf::ApplyFromVarSet(VarSet &v)
|
||||
reconnect=atoi(v.Get("RECONNECT").c_str());
|
||||
realmport=atoi(v.Get("REALMPORT").c_str());
|
||||
client=atoi(v.Get("CLIENT").c_str());
|
||||
if(client==9) //9 = Custom settings
|
||||
{
|
||||
clientversion_string=v.Get("CLIENTVERSION");
|
||||
clientbuild=atoi(v.Get("CLIENTBUILD").c_str());
|
||||
}
|
||||
clientlang=v.Get("CLIENTLANGUAGE");
|
||||
realmname=v.Get("REALMNAME");
|
||||
charname=v.Get("CHARNAME");
|
||||
@ -524,25 +519,25 @@ void PseuInstanceConf::ApplyFromVarSet(VarSet &v)
|
||||
|
||||
switch(client)
|
||||
{
|
||||
case 0:
|
||||
case CLIENT_CLASSIC_WOW:
|
||||
{
|
||||
clientbuild = 6005;
|
||||
clientversion_string="1.12.2";
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
case CLIENT_TBC:
|
||||
{
|
||||
clientbuild = 8606;
|
||||
clientversion_string="2.4.3";
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
case CLIENT_WOTLK:
|
||||
{
|
||||
clientbuild = 12340;
|
||||
clientversion_string="3.3.5";
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
case CLIENT_CATA:
|
||||
default:
|
||||
{
|
||||
logerror("Unknown client - check conf");
|
||||
|
||||
@ -29,6 +29,14 @@ enum InstanceConditions
|
||||
COND_MAX
|
||||
};
|
||||
|
||||
enum Client
|
||||
{
|
||||
CLIENT_UNKNOWN,
|
||||
CLIENT_CLASSIC_WOW,
|
||||
CLIENT_TBC,
|
||||
CLIENT_WOTLK,
|
||||
CLIENT_CATA
|
||||
};
|
||||
|
||||
class PseuInstanceConf
|
||||
{
|
||||
|
||||
@ -248,9 +248,9 @@ void RealmSession::_HandleRealmList(ByteBuffer& pkt)
|
||||
std::string realmAddr;
|
||||
|
||||
SRealmHeader rh;
|
||||
uint16 cb = GetInstance()->GetConf()->clientbuild;
|
||||
uint16 client = GetInstance()->GetConf()->client;
|
||||
pkt >> rh.cmd >> rh.size >> rh.unknown;
|
||||
if(cb<=6005)
|
||||
if(client==CLIENT_CLASSIC_WOW)
|
||||
{
|
||||
uint8 count;
|
||||
pkt >> count;
|
||||
@ -272,7 +272,7 @@ void RealmSession::_HandleRealmList(ByteBuffer& pkt)
|
||||
// readout realms
|
||||
for(uint8 i=0;i<rh.count;i++)
|
||||
{
|
||||
if(cb<=6005)
|
||||
if(client==CLIENT_CLASSIC_WOW)
|
||||
{
|
||||
uint32 icon;
|
||||
pkt >> icon;
|
||||
@ -539,9 +539,7 @@ void RealmSession::_HandleLogonChallenge(ByteBuffer& pkt)
|
||||
packet.append(M1hash.GetDigest(),M1hash.GetLength());
|
||||
packet.append(crc_hash,20);
|
||||
packet << (uint8)0; // number of keys = 0
|
||||
|
||||
if(GetInstance()->GetConf()->clientbuild > 5302)
|
||||
packet << (uint8)0; // 1.11.x compatibility (needs one more 0)
|
||||
packet << (uint8)0; // 1.11.x compatibility (needs one more 0)
|
||||
|
||||
GetInstance()->SetSessionKey(_key);
|
||||
memcpy(this->_m2,M2hash.GetDigest(),M2hash.GetLength()); // save M2 to an extern var to check it later
|
||||
@ -561,7 +559,7 @@ void RealmSession::_HandleLogonChallenge(ByteBuffer& pkt)
|
||||
void RealmSession::_HandleLogonProof(ByteBuffer& pkt)
|
||||
{
|
||||
PseuGUI *gui = GetInstance()->GetGUI();
|
||||
logdebug("RealmSocket: Got AUTH_LOGON_PROOF [%u of %u bytes]",pkt.size(),(GetInstance()->GetConf()->clientbuild>6005 ? sizeof(sAuthLogonProof_S) : sizeof(sAuthLogonProof_S_6005)));
|
||||
logdebug("RealmSocket: Got AUTH_LOGON_PROOF [%u of %u bytes]",pkt.size(),(GetInstance()->GetConf()->client>CLIENT_CLASSIC_WOW ? sizeof(sAuthLogonProof_S) : sizeof(sAuthLogonProof_S_6005)));
|
||||
if(pkt.size() < 2)
|
||||
{
|
||||
logerror("AUTH_LOGON_PROOF: Recieved incorrect/unknown packet. Hexdump:");
|
||||
@ -612,7 +610,7 @@ void RealmSession::_HandleLogonProof(ByteBuffer& pkt)
|
||||
|
||||
|
||||
sAuthLogonProof_S lp;
|
||||
if(GetInstance()->GetConf()->clientbuild<=6005)
|
||||
if(GetInstance()->GetConf()->client==CLIENT_CLASSIC_WOW)
|
||||
{
|
||||
sAuthLogonProof_S_6005 lp6005;
|
||||
pkt.read((uint8*)&lp6005, sizeof(sAuthLogonProof_S_6005));
|
||||
|
||||
@ -2,13 +2,13 @@
|
||||
|
||||
Bag::Bag() : Item()
|
||||
{
|
||||
_type |= TYPE_CONTAINER;
|
||||
_typeid = TYPEID_CONTAINER;
|
||||
_valuescount = CONTAINER_END;
|
||||
_slot = 0;
|
||||
}
|
||||
|
||||
void Bag::Create(uint64 guid)
|
||||
{
|
||||
Item::Create(guid);
|
||||
}
|
||||
_type |= TYPE_CONTAINER;
|
||||
_typeid = TYPEID_CONTAINER;
|
||||
_valuescount = Object::maxvalues[_typeid];
|
||||
_slot = 0;
|
||||
}
|
||||
|
||||
void Bag::Create(uint64 guid)
|
||||
{
|
||||
Item::Create(guid);
|
||||
}
|
||||
|
||||
@ -81,9 +81,12 @@ void Channel::Join(std::string channel, std::string password)
|
||||
// Send join channel request
|
||||
WorldPacket worldPacket;
|
||||
worldPacket.SetOpcode(CMSG_JOIN_CHANNEL);
|
||||
worldPacket << (uint32)0; // new since 2.0.x, some channel ID? server answers us with that number later if channel joined
|
||||
worldPacket << (uint8)0; // unk
|
||||
worldPacket << (uint8)0; // unk, new since 2.2.x
|
||||
if(_worldSession->GetInstance()->GetConf()->client > CLIENT_CLASSIC_WOW)
|
||||
{
|
||||
worldPacket << (uint32)0; // new since 2.0.x, some channel ID? server answers us with that number later if channel joined
|
||||
worldPacket << (uint8)0; // unk
|
||||
worldPacket << (uint8)0; // unk, new since 2.2.x
|
||||
}
|
||||
worldPacket << channel << password;
|
||||
_worldSession->SendWorldPacket(worldPacket);
|
||||
}
|
||||
|
||||
@ -4,10 +4,10 @@ Corpse::Corpse()
|
||||
{
|
||||
_type=TYPE_CORPSE;
|
||||
_typeid=TYPEID_CORPSE;
|
||||
_valuescount=CORPSE_END;
|
||||
_valuescount=Object::maxvalues[_typeid];
|
||||
}
|
||||
|
||||
void Corpse::Create(uint64 guid)
|
||||
{
|
||||
Object::Create(guid);
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,10 +5,10 @@ DynamicObject::DynamicObject() : WorldObject()
|
||||
_uint32values=NULL;
|
||||
_type=TYPE_DYNAMICOBJECT;
|
||||
_typeid=TYPEID_DYNAMICOBJECT;
|
||||
_valuescount=DYNAMICOBJECT_END;
|
||||
_valuescount=Object::maxvalues[_typeid];
|
||||
}
|
||||
|
||||
void DynamicObject::Create(uint64 guid)
|
||||
{
|
||||
Object::Create(guid);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,12 +3,12 @@
|
||||
GameObject::GameObject() : WorldObject()
|
||||
{
|
||||
_uint32values=NULL;
|
||||
_type=TYPE_GAMEOBJECT;
|
||||
_type|=TYPE_GAMEOBJECT;
|
||||
_typeid=TYPEID_GAMEOBJECT;
|
||||
_valuescount=GAMEOBJECT_END;
|
||||
_valuescount=Object::maxvalues[_typeid];
|
||||
}
|
||||
|
||||
void GameObject::Create(uint64 guid)
|
||||
{
|
||||
Object::Create(guid);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
#include "WorldSession.h"
|
||||
#include "UpdateFields.h"
|
||||
|
||||
#include "Item.h"
|
||||
#include "Bag.h"
|
||||
@ -18,7 +17,10 @@ void WorldSession::_HandleItemQuerySingleResponseOpcode(WorldPacket& recvPacket)
|
||||
proto->Id = ItemID;
|
||||
recvPacket >> proto->Class;
|
||||
recvPacket >> proto->SubClass;
|
||||
recvPacket >> unk; // dont need that value?
|
||||
if(GetInstance()->GetConf()->client > CLIENT_CLASSIC_WOW)
|
||||
{
|
||||
recvPacket >> unk; // dont need that value?
|
||||
}
|
||||
recvPacket >> proto->Name;
|
||||
recvPacket >> unk8;
|
||||
recvPacket >> unk8;
|
||||
@ -132,7 +134,7 @@ Item::Item()
|
||||
_type |= TYPE_ITEM;
|
||||
_typeid = TYPEID_ITEM;
|
||||
|
||||
_valuescount = ITEM_END;
|
||||
_valuescount = Object::maxvalues[_typeid];
|
||||
_slot = 0;
|
||||
//_bag = NULL; // not yet implemented
|
||||
}
|
||||
|
||||
@ -9,7 +9,7 @@ CacheHandler.h GameObject.h ObjectDefines.h Unit.cpp WorldP
|
||||
Channel.cpp Item.cpp Object.h Unit.h WorldSession.cpp\
|
||||
Channel.h Item.h ObjMgr.cpp UpdateData.cpp WorldSession.h\
|
||||
CMSGConstructor.cpp ObjMgr.h UpdateData.h WorldSocket.cpp\
|
||||
Corpse.cpp MapMgr.cpp Opcodes.cpp UpdateFields.h WorldSocket.h\
|
||||
Corpse.cpp MapMgr.cpp Opcodes.cpp UpdateFields.cpp WorldSocket.h\
|
||||
Corpse.h MapMgr.h Opcodes.h UpdateMask.h
|
||||
|
||||
libworld_a_LIBADD = ../../shared/libshared.a ../../shared/Auth/libauth.a ../../shared/Network/libnetwork.a
|
||||
|
||||
@ -127,12 +127,18 @@ void MapMgr::_LoadTile(uint32 gx, uint32 gy, uint32 m)
|
||||
bb.append(mdr.data.ptr,mdr.data.size);
|
||||
MemoryDataHolder::Delete(buf);
|
||||
ADTFile *adt = new ADTFile();
|
||||
adt->LoadMem(bb);
|
||||
logdebug("MAPMGR: Loaded ADT '%s'",buf);
|
||||
MapTile *tile = new MapTile();
|
||||
tile->ImportFromADT(adt);
|
||||
if(adt->LoadMem(bb))
|
||||
{
|
||||
logdebug("MAPMGR: Loaded ADT '%s'",buf);
|
||||
MapTile *tile = new MapTile();
|
||||
tile->ImportFromADT(adt);
|
||||
_tiles->SetTile(tile,gx,gy);
|
||||
}
|
||||
else
|
||||
{
|
||||
logerror("MAPMGR: Error loading ADT '%s'",buf);//This should not happen!!
|
||||
}
|
||||
delete adt;
|
||||
_tiles->SetTile(tile,gx,gy);
|
||||
logdebug("MAPMGR: Imported MapTile (%u, %u) for map %u",gx,gy,m);
|
||||
}
|
||||
else
|
||||
|
||||
115
src/Client/World/MovementInfo.h
Normal file
115
src/Client/World/MovementInfo.h
Normal file
@ -0,0 +1,115 @@
|
||||
#ifndef _MOVEMENTINFO_H
|
||||
#define _MOVEMENTINFO_H
|
||||
|
||||
enum MovementFlags
|
||||
{
|
||||
MOVEMENTFLAG_NONE = 0x00000000,
|
||||
MOVEMENTFLAG_FORWARD = 0x00000001,
|
||||
MOVEMENTFLAG_BACKWARD = 0x00000002,
|
||||
MOVEMENTFLAG_STRAFE_LEFT = 0x00000004,
|
||||
MOVEMENTFLAG_STRAFE_RIGHT = 0x00000008,
|
||||
MOVEMENTFLAG_TURN_LEFT = 0x00000010,
|
||||
MOVEMENTFLAG_TURN_RIGHT = 0x00000020,
|
||||
MOVEMENTFLAG_PITCH_UP = 0x00000040,
|
||||
MOVEMENTFLAG_PITCH_DOWN = 0x00000080,
|
||||
MOVEMENTFLAG_WALK_MODE = 0x00000100, // Walking
|
||||
MOVEMENTFLAG_ONTRANSPORT = 0x00000200,
|
||||
MOVEMENTFLAG_LEVITATING = 0x00000400,
|
||||
MOVEMENTFLAG_ROOT = 0x00000800,
|
||||
MOVEMENTFLAG_FALLING = 0x00001000,
|
||||
MOVEMENTFLAG_FALLINGFAR = 0x00002000,
|
||||
MOVEMENTFLAG_PENDINGSTOP = 0x00004000,
|
||||
MOVEMENTFLAG_PENDINGSTRAFESTOP = 0x00008000,
|
||||
MOVEMENTFLAG_PENDINGFORWARD = 0x00010000,
|
||||
MOVEMENTFLAG_PENDINGBACKWARD = 0x00020000,
|
||||
MOVEMENTFLAG_PENDINGSTRAFELEFT = 0x00040000,
|
||||
MOVEMENTFLAG_PENDINGSTRAFERIGHT = 0x00080000,
|
||||
MOVEMENTFLAG_PENDINGROOT = 0x00100000,
|
||||
MOVEMENTFLAG_SWIMMING = 0x00200000, // appears with fly flag also
|
||||
MOVEMENTFLAG_ASCENDING = 0x00400000, // swim up also
|
||||
MOVEMENTFLAG_DESCENDING = 0x00800000, // swim down also
|
||||
MOVEMENTFLAG_CAN_FLY = 0x01000000, // can fly in 3.3?
|
||||
MOVEMENTFLAG_FLYING = 0x02000000, // Actual flying mode
|
||||
MOVEMENTFLAG_SPLINE_ELEVATION = 0x04000000, // used for flight paths
|
||||
MOVEMENTFLAG_SPLINE_ENABLED = 0x08000000, // used for flight paths
|
||||
MOVEMENTFLAG_WATERWALKING = 0x10000000, // prevent unit from falling through water
|
||||
MOVEMENTFLAG_SAFE_FALL = 0x20000000, // active rogue safe fall spell (passive)
|
||||
MOVEMENTFLAG_HOVER = 0x40000000
|
||||
};
|
||||
|
||||
enum MovementFlags2
|
||||
{
|
||||
MOVEMENTFLAG2_NONE = 0x0000,
|
||||
MOVEMENTFLAG2_UNK1 = 0x0001,
|
||||
MOVEMENTFLAG2_UNK2 = 0x0002,
|
||||
MOVEMENTFLAG2_UNK3 = 0x0004,
|
||||
MOVEMENTFLAG2_FULLSPEEDTURNING = 0x0008,
|
||||
MOVEMENTFLAG2_FULLSPEEDPITCHING = 0x0010,
|
||||
MOVEMENTFLAG2_ALLOW_PITCHING = 0x0020,
|
||||
MOVEMENTFLAG2_UNK4 = 0x0040,
|
||||
MOVEMENTFLAG2_UNK5 = 0x0080,
|
||||
MOVEMENTFLAG2_UNK6 = 0x0100,
|
||||
MOVEMENTFLAG2_UNK7 = 0x0200,
|
||||
MOVEMENTFLAG2_INTERP_MOVEMENT = 0x0400,
|
||||
MOVEMENTFLAG2_INTERP_TURNING = 0x0800,
|
||||
MOVEMENTFLAG2_INTERP_PITCHING = 0x1000,
|
||||
MOVEMENTFLAG2_UNK8 = 0x2000,
|
||||
MOVEMENTFLAG2_UNK9 = 0x4000,
|
||||
MOVEMENTFLAG2_UNK10 = 0x8000,
|
||||
MOVEMENTFLAG2_INTERP_MASK = MOVEMENTFLAG2_INTERP_MOVEMENT | MOVEMENTFLAG2_INTERP_TURNING | MOVEMENTFLAG2_INTERP_PITCHING
|
||||
};
|
||||
struct MovementInfo
|
||||
{
|
||||
static uint8 _c; //Version switch helper
|
||||
|
||||
// Read/Write methods
|
||||
void Read(ByteBuffer &data);
|
||||
void Write(ByteBuffer &data) const;
|
||||
|
||||
// common
|
||||
uint32 flags;
|
||||
uint16 flags2;
|
||||
uint32 time;
|
||||
WorldPosition pos;
|
||||
// transport
|
||||
uint64 t_guid;
|
||||
WorldPosition t_pos;
|
||||
uint32 t_time, t_time2;
|
||||
uint8 t_seat;
|
||||
// swimming and unk
|
||||
float s_angle;
|
||||
// last fall time
|
||||
uint32 fallTime;
|
||||
// jumping
|
||||
float j_velocity, j_sinAngle, j_cosAngle, j_xyspeed;
|
||||
// spline
|
||||
float u_unk1;
|
||||
|
||||
MovementInfo()
|
||||
{
|
||||
flags = time = t_time = fallTime = flags2 = 0;
|
||||
t_seat = 0;
|
||||
s_angle = j_velocity = j_sinAngle = j_cosAngle = j_xyspeed = u_unk1 = 0.0f;
|
||||
t_guid = 0;
|
||||
}
|
||||
|
||||
void SetMovementFlags(uint32 _flags)
|
||||
{
|
||||
flags = _flags;
|
||||
}
|
||||
};
|
||||
|
||||
inline ByteBuffer& operator<< (ByteBuffer& buf, MovementInfo const& mi)
|
||||
{
|
||||
mi.Write(buf);
|
||||
return buf;
|
||||
}
|
||||
|
||||
inline ByteBuffer& operator>> (ByteBuffer& buf, MovementInfo& mi)
|
||||
{
|
||||
mi.Read(buf);
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
@ -3,6 +3,7 @@
|
||||
#include "World.h"
|
||||
#include "MovementMgr.h"
|
||||
#include "Player.h"
|
||||
#include "MovementInfo.h"
|
||||
|
||||
MovementMgr::MovementMgr()
|
||||
{
|
||||
@ -33,32 +34,18 @@ void MovementMgr::SetInstance(PseuInstance *inst)
|
||||
void MovementMgr::_BuildPacket(uint16 opcode)
|
||||
{
|
||||
WorldPacket *wp = new WorldPacket(opcode,4+2+4+16); // it can be larger, if we are jumping, on transport or swimming
|
||||
wp->appendPackGUID(_mychar->GetGUID());
|
||||
*wp << _moveFlags;
|
||||
*wp << (uint16)0; // flags2 , safe to set 0 for now (shlainn)
|
||||
*wp << getMSTime();
|
||||
*wp << _mychar->GetPosition();
|
||||
// TODO: transport not yet handled/done
|
||||
if(_moveFlags & MOVEMENTFLAG_ONTRANSPORT)
|
||||
{
|
||||
*wp << (uint64)0; // transport guid
|
||||
*wp << WorldPosition(); // transport position
|
||||
*wp << getMSTime(); // transport time (??)
|
||||
}
|
||||
// TODO: swimming not yet done
|
||||
if(_moveFlags & MOVEMENTFLAG_SWIMMING)
|
||||
{
|
||||
*wp << (float)0; // angle; 1.55=looking up, -1.55=looking down, 0=looking forward
|
||||
}
|
||||
*wp << (uint32)0; // last fall time (also used when jumping)
|
||||
if(_moveFlags & MOVEMENTFLAG_PENDINGSTOP)
|
||||
{
|
||||
*wp << (float)0; //unk value, or as mangos calls it: j_unk ^^
|
||||
*wp << sin(_mychar->GetO()+ (M_PI/2));
|
||||
*wp << cos(_mychar->GetO()+ (M_PI/2));
|
||||
*wp << _movespeed;
|
||||
}
|
||||
if(_instance->GetConf()->client > CLIENT_TBC)
|
||||
wp->appendPackGUID(_mychar->GetGUID());
|
||||
MovementInfo mi;
|
||||
mi.SetMovementFlags(_moveFlags);
|
||||
mi.time = getMSTime();
|
||||
mi.pos = _mychar->GetPosition();
|
||||
mi.fallTime = _falltime;
|
||||
*wp << mi;
|
||||
|
||||
// TODO: transport not yet handled/done
|
||||
// TODO: swimming not yet done
|
||||
// TODO: jumping not done yet
|
||||
// TODO: spline not yet done
|
||||
|
||||
DEBUG(logdebug("Move flags: 0x%X (packet: %u bytes)",_moveFlags,wp->size()));
|
||||
@ -66,6 +53,8 @@ void MovementMgr::_BuildPacket(uint16 opcode)
|
||||
_instance->GetWSession()->AddSendWorldPacket(wp);
|
||||
_moved = true;
|
||||
_optime = getMSTime();
|
||||
_falltime = 0; //HACK!!!!
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -171,6 +160,12 @@ void MovementMgr::MoveStop(void)
|
||||
_BuildPacket(MSG_MOVE_STOP);
|
||||
}
|
||||
|
||||
void MovementMgr::MoveFallLand(void)
|
||||
{
|
||||
Update(true);
|
||||
_BuildPacket(MSG_MOVE_FALL_LAND);
|
||||
}
|
||||
|
||||
void MovementMgr::MoveStartForward(void)
|
||||
{
|
||||
if(_moveFlags & MOVEMENTFLAG_FORWARD)
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
#define MOVEMENTMGR_H
|
||||
|
||||
#include "common.h"
|
||||
#include "UpdateData.h"
|
||||
#include "MovementInfo.h"
|
||||
|
||||
#define MOVE_HEARTBEAT_DELAY 500
|
||||
#define MOVE_TURN_UPDATE_DIFF 0.15f // not sure about original/real value, but this seems good
|
||||
@ -58,7 +58,7 @@ public:
|
||||
bool IsTurning(void); // spinning around?
|
||||
bool IsWalking(void); // walking straight forward/backward?
|
||||
bool IsStrafing(void); // strafing left/right?
|
||||
|
||||
inline void SetFallTime(uint32 falltime){_falltime = falltime; }
|
||||
|
||||
|
||||
private:
|
||||
@ -71,6 +71,7 @@ private:
|
||||
uint8 _movemode; // automatic or manual
|
||||
float _movespeed; // current xy movement speed
|
||||
float _jumptime;
|
||||
uint32 _falltime;
|
||||
UnitMoveType _movetype; // index used for speed selection
|
||||
bool _moved;
|
||||
|
||||
|
||||
@ -9,7 +9,7 @@ Object::Object()
|
||||
_uint32values=NULL;
|
||||
_type=TYPE_OBJECT;
|
||||
_typeid=TYPEID_OBJECT;
|
||||
_valuescount=OBJECT_END; // base class. this value will be set by derived classes
|
||||
_valuescount=Object::maxvalues[_typeid]; // base class. this value will be set by derived classes
|
||||
}
|
||||
|
||||
Object::~Object()
|
||||
@ -110,7 +110,9 @@ void WorldSession::_HandleDestroyObjectOpcode(WorldPacket& recvPacket)
|
||||
uint64 guid;
|
||||
uint8 dummy;
|
||||
|
||||
recvPacket >> guid >> dummy;
|
||||
recvPacket >> guid;
|
||||
if(GetInstance()->GetConf()->client > CLIENT_TBC)
|
||||
recvPacket >> dummy;
|
||||
logdebug("Destroy Object "I64FMT,guid);
|
||||
|
||||
// call script just before object removal
|
||||
|
||||
@ -7,6 +7,14 @@
|
||||
#include "HelperDefs.h"
|
||||
#include "World.h"
|
||||
|
||||
struct UpdateField
|
||||
{
|
||||
UpdateField(){};
|
||||
UpdateField(uint16 o, uint16 t):offset(o),type(t){};
|
||||
uint16 offset;
|
||||
uint16 type;
|
||||
};
|
||||
|
||||
enum TYPE
|
||||
{
|
||||
TYPE_OBJECT = 1,
|
||||
@ -32,16 +40,17 @@ enum TYPEID
|
||||
TYPEID_DYNAMICOBJECT = 6,
|
||||
TYPEID_CORPSE = 7,
|
||||
TYPEID_AIGROUP = 8,
|
||||
TYPEID_AREATRIGGER = 9
|
||||
TYPEID_AREATRIGGER = 9,
|
||||
TYPEID_MAX
|
||||
};
|
||||
|
||||
class Object
|
||||
{
|
||||
public:
|
||||
virtual ~Object();
|
||||
inline const uint64 GetGUID() const { return GetUInt64Value(0); }
|
||||
inline const uint32 GetGUIDLow() const { return GetUInt32Value(0); }
|
||||
inline const uint32 GetGUIDHigh() const { return GetUInt32Value(1); }
|
||||
inline const uint64 GetGUID() const { return GetUInt64Value(OBJECT_FIELD_GUID); }
|
||||
inline const uint32 GetGUIDLow() const { return GetUInt32Value(OBJECT_FIELD_GUID_LOW); }
|
||||
inline const uint32 GetGUIDHigh() const { return GetUInt32Value(OBJECT_FIELD_GUID_HIGH); }
|
||||
inline uint32 GetEntry() const { return GetUInt32Value(OBJECT_FIELD_ENTRY); }
|
||||
inline uint16 GetValuesCount(void) { return _valuescount; }
|
||||
|
||||
@ -57,35 +66,39 @@ public:
|
||||
inline bool IsDynObject(void) { return _typeid == TYPEID_DYNAMICOBJECT; } // specific
|
||||
inline bool IsGameObject(void) { return _typeid == TYPEID_GAMEOBJECT; } // specific
|
||||
inline bool IsWorldObject(void) { return _type & (TYPE_PLAYER | TYPE_UNIT | TYPE_CORPSE | TYPE_DYNAMICOBJECT | TYPE_GAMEOBJECT); }
|
||||
inline const uint32 GetUInt32Value( uint16 index ) const
|
||||
inline const uint32 GetUInt32Value( UpdateFieldName index ) const
|
||||
{
|
||||
return _uint32values[ index ];
|
||||
return _uint32values[ Object::updatefields[index].offset ];
|
||||
}
|
||||
|
||||
inline const uint64 GetUInt64Value( uint16 index ) const
|
||||
inline const uint64 GetUInt64Value( UpdateFieldName index ) const
|
||||
{
|
||||
return *((uint64*)&(_uint32values[ index ]));
|
||||
return *((uint64*)&(_uint32values[ Object::updatefields[index].offset ]));
|
||||
}
|
||||
|
||||
inline bool HasFlag( uint16 index, uint32 flag ) const
|
||||
inline bool HasFlag( UpdateFieldName index, uint32 flag ) const
|
||||
{
|
||||
return (_uint32values[ index ] & flag) != 0;
|
||||
return (_uint32values[ Object::updatefields[index].offset ] & flag) != 0;
|
||||
}
|
||||
inline const float GetFloatValue( uint16 index ) const
|
||||
inline const float GetFloatValue( UpdateFieldName index ) const
|
||||
{
|
||||
return _floatvalues[ index ];
|
||||
return _floatvalues[ Object::updatefields[index].offset ];
|
||||
}
|
||||
inline void SetFloatValue( uint16 index, float value )
|
||||
inline void SetFloatValue( UpdateFieldName index, float value )
|
||||
{
|
||||
_floatvalues[ index ] = value;
|
||||
_floatvalues[ Object::updatefields[index].offset ] = value;
|
||||
}
|
||||
inline void SetUInt32Value( uint16 index, uint32 value )
|
||||
inline void SetUInt32Value( UpdateFieldName index, uint32 value )
|
||||
{
|
||||
_uint32values[ index ] = value;
|
||||
_uint32values[ Object::updatefields[index].offset ] = value;
|
||||
}
|
||||
inline void SetUInt64Value( uint16 index, uint64 value )
|
||||
inline void SetUInt32Value( uint16 offset, uint32 value )
|
||||
{
|
||||
*((uint64*)&(_uint32values[ index ])) = value;
|
||||
_uint32values[ offset ] = value;
|
||||
}
|
||||
inline void SetUInt64Value( UpdateFieldName index, uint64 value )
|
||||
{
|
||||
*((uint64*)&(_uint32values[ Object::updatefields[index].offset ])) = value;
|
||||
}
|
||||
|
||||
inline void SetName(std::string name) { _name = name; }
|
||||
@ -93,13 +106,16 @@ public:
|
||||
|
||||
inline float GetObjectSize() const
|
||||
{
|
||||
return ( _valuescount > UNIT_FIELD_BOUNDINGRADIUS ) ? _floatvalues[UNIT_FIELD_BOUNDINGRADIUS] : 0.39f;
|
||||
return ( _valuescount > Object::updatefields[UNIT_FIELD_BOUNDINGRADIUS].offset ) ? _floatvalues[Object::updatefields[UNIT_FIELD_BOUNDINGRADIUS].offset] : 0.39f;
|
||||
}
|
||||
|
||||
void Create(uint64 guid);
|
||||
inline bool _IsDepleted(void) { return _depleted; }
|
||||
inline void _SetDepleted(void) { _depleted = true; }
|
||||
|
||||
static uint32 maxvalues[];
|
||||
static UpdateField updatefields[];
|
||||
|
||||
protected:
|
||||
Object();
|
||||
void _InitValues(void);
|
||||
@ -114,8 +130,10 @@ protected:
|
||||
uint8 _typeid;
|
||||
std::string _name;
|
||||
bool _depleted : 1; // true if the object was deleted from the objmgr, but not from memory
|
||||
|
||||
};
|
||||
|
||||
|
||||
class WorldObject : public Object
|
||||
{
|
||||
public:
|
||||
@ -145,17 +163,8 @@ protected:
|
||||
|
||||
inline uint32 GetValuesCountByTypeId(uint8 tid)
|
||||
{
|
||||
switch(tid)
|
||||
{
|
||||
case TYPEID_OBJECT: return OBJECT_END;
|
||||
case TYPEID_UNIT: return UNIT_END;
|
||||
case TYPEID_PLAYER: return PLAYER_END;
|
||||
case TYPEID_ITEM: return ITEM_END;
|
||||
case TYPEID_CONTAINER: return CONTAINER_END;
|
||||
case TYPEID_GAMEOBJECT: return GAMEOBJECT_END;
|
||||
case TYPEID_DYNAMICOBJECT: return DYNAMICOBJECT_END;
|
||||
case TYPEID_CORPSE: return CORPSE_END;
|
||||
}
|
||||
if(tid < TYPEID_MAX)
|
||||
return Object::maxvalues[tid];
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -13,7 +13,7 @@ Player::Player() : Unit()
|
||||
{
|
||||
_type |= TYPE_PLAYER;
|
||||
_typeid = TYPEID_PLAYER;
|
||||
_valuescount = PLAYER_END;
|
||||
_valuescount = Object::maxvalues[_typeid];
|
||||
}
|
||||
|
||||
void Player::Create(uint64 guid)
|
||||
@ -71,4 +71,4 @@ uint16 MyCharacter::GetSpellSlot(uint32 spellid)
|
||||
if(i->id == spellid)
|
||||
return i->slot;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,7 +5,7 @@ Unit::Unit() : WorldObject()
|
||||
{
|
||||
_type |= TYPE_UNIT;
|
||||
_typeid = TYPEID_UNIT;
|
||||
_valuescount = UNIT_END;
|
||||
_valuescount = Object::maxvalues[_typeid];
|
||||
}
|
||||
|
||||
void Unit::Create(uint64 guid)
|
||||
|
||||
@ -66,6 +66,8 @@ struct CreatureTemplate
|
||||
uint8 RacialLeader;
|
||||
uint32 questItems[4];
|
||||
uint32 movementId;
|
||||
uint32 PetSpellDataId;
|
||||
uint16 civilian;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -2,7 +2,6 @@
|
||||
#include "ZCompressor.h"
|
||||
#include "WorldSession.h"
|
||||
#include "UpdateData.h"
|
||||
#include "UpdateFields.h"
|
||||
#include "Object.h"
|
||||
#include "Unit.h"
|
||||
#include "Bag.h"
|
||||
@ -11,6 +10,7 @@
|
||||
#include "DynamicObject.h"
|
||||
#include "ObjMgr.h"
|
||||
#include "UpdateMask.h"
|
||||
#include "MovementInfo.h"
|
||||
|
||||
|
||||
void WorldSession::_HandleCompressedUpdateObjectOpcode(WorldPacket& recvPacket)
|
||||
@ -37,11 +37,13 @@ void WorldSession::_HandleCompressedUpdateObjectOpcode(WorldPacket& recvPacket)
|
||||
void WorldSession::_HandleUpdateObjectOpcode(WorldPacket& recvPacket)
|
||||
{
|
||||
uint8 utype;
|
||||
//uint8 hasTransport;
|
||||
uint8 hasTransport;
|
||||
uint32 usize, ublocks, readblocks=0;
|
||||
uint64 uguid;
|
||||
recvPacket >> ublocks; // >> hasTransport;
|
||||
//logdev("UpdateObject: blocks = %u, hasTransport = %u", ublocks, hasTransport);
|
||||
if(GetInstance()->GetConf()->client <= CLIENT_TBC)
|
||||
recvPacket >> hasTransport;
|
||||
|
||||
logdev("UpdateObject: blocks = %u", ublocks);
|
||||
while((recvPacket.rpos() < recvPacket.size())&& (readblocks < ublocks))
|
||||
{
|
||||
@ -50,7 +52,7 @@ void WorldSession::_HandleUpdateObjectOpcode(WorldPacket& recvPacket)
|
||||
{
|
||||
case UPDATETYPE_VALUES:
|
||||
{
|
||||
uguid = recvPacket.GetPackedGuid();
|
||||
uguid = recvPacket.readPackGUID();
|
||||
_ValuesUpdate(uguid,recvPacket);
|
||||
}
|
||||
break;
|
||||
@ -76,7 +78,7 @@ void WorldSession::_HandleUpdateObjectOpcode(WorldPacket& recvPacket)
|
||||
case UPDATETYPE_CREATE_OBJECT2: // will be sent when our very own character is created
|
||||
case UPDATETYPE_CREATE_OBJECT: // will be sent on any other object creation
|
||||
{
|
||||
uguid = recvPacket.GetPackedGuid();
|
||||
uguid = recvPacket.readPackGUID();
|
||||
uint8 objtypeid;
|
||||
recvPacket >> objtypeid;
|
||||
logdebug("Create Object type %u with guid "I64FMT,objtypeid,uguid);
|
||||
@ -127,6 +129,7 @@ void WorldSession::_HandleUpdateObjectOpcode(WorldPacket& recvPacket)
|
||||
Unit *unit = new Unit();
|
||||
unit->Create(uguid);
|
||||
objmgr.Add(unit);
|
||||
logdebug("Created Unit with guid "I64FMT,uguid);
|
||||
break;
|
||||
}
|
||||
case TYPEID_PLAYER:
|
||||
@ -136,6 +139,7 @@ void WorldSession::_HandleUpdateObjectOpcode(WorldPacket& recvPacket)
|
||||
Player *player = new Player();
|
||||
player->Create(uguid);
|
||||
objmgr.Add(player);
|
||||
logdebug("Created Player with guid "I64FMT,uguid);
|
||||
break;
|
||||
}
|
||||
case TYPEID_GAMEOBJECT:
|
||||
@ -143,6 +147,7 @@ void WorldSession::_HandleUpdateObjectOpcode(WorldPacket& recvPacket)
|
||||
GameObject *go = new GameObject();
|
||||
go->Create(uguid);
|
||||
objmgr.Add(go);
|
||||
logdebug("Created GO with guid "I64FMT,uguid);
|
||||
break;
|
||||
}
|
||||
case TYPEID_CORPSE:
|
||||
@ -150,6 +155,7 @@ void WorldSession::_HandleUpdateObjectOpcode(WorldPacket& recvPacket)
|
||||
Corpse *corpse = new Corpse();
|
||||
corpse->Create(uguid);
|
||||
objmgr.Add(corpse);
|
||||
logdebug("Created Corpse with guid "I64FMT,uguid);
|
||||
break;
|
||||
}
|
||||
case TYPEID_DYNAMICOBJECT:
|
||||
@ -157,6 +163,7 @@ void WorldSession::_HandleUpdateObjectOpcode(WorldPacket& recvPacket)
|
||||
DynamicObject *dobj = new DynamicObject();
|
||||
dobj->Create(uguid);
|
||||
objmgr.Add(dobj);
|
||||
logdebug("Created DynObj with guid "I64FMT,uguid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -180,6 +187,7 @@ void WorldSession::_HandleUpdateObjectOpcode(WorldPacket& recvPacket)
|
||||
Set.defaultarg = toString(uguid);
|
||||
Set.arg[0] = toString(objtypeid);
|
||||
GetInstance()->GetScripts()->RunScript("_onobjectcreate", &Set);
|
||||
|
||||
}
|
||||
|
||||
// if our own character got finally created, we have successfully entered the world,
|
||||
@ -192,7 +200,7 @@ void WorldSession::_HandleUpdateObjectOpcode(WorldPacket& recvPacket)
|
||||
recvPacket >> usize;
|
||||
for(uint16 i=0;i<usize;i++)
|
||||
{
|
||||
uguid = recvPacket.GetPackedGuid(); // not 100% sure if this is correct
|
||||
uguid = recvPacket.readPackGUID(); // not 100% sure if this is correct
|
||||
logdebug("GUID "I64FMT" out of range",uguid);
|
||||
|
||||
// call script just before object removal
|
||||
@ -238,10 +246,13 @@ void WorldSession::_MovementUpdate(uint8 objtypeid, uint64 uguid, WorldPacket& r
|
||||
{
|
||||
MovementInfo mi; // TODO: use a reference to a MovementInfo in Unit/Player class once implemented
|
||||
uint16 flags;
|
||||
uint8 flags_6005;
|
||||
// uint64 fullguid; // see below
|
||||
float speedWalk, speedRun, speedSwimBack, speedSwim, speedWalkBack, speedTurn, speedFly, speedFlyBack, speedPitchRate;
|
||||
float speedWalk =0, speedRun =0, speedSwimBack =0, speedSwim =0, speedWalkBack =0, speedTurn =0, speedFly =0, speedFlyBack =0, speedPitchRate =0;
|
||||
uint32 unk32;
|
||||
|
||||
uint16 client = GetInstance()->GetConf()->client;
|
||||
|
||||
Object *obj = (Object*)objmgr.GetObj(uguid, true); // also depleted objects
|
||||
Unit *u = NULL;
|
||||
if(obj)
|
||||
@ -256,57 +267,55 @@ void WorldSession::_MovementUpdate(uint8 objtypeid, uint64 uguid, WorldPacket& r
|
||||
logerror("MovementUpdate for unknown object "I64FMT" typeid=%u",uguid,objtypeid);
|
||||
}
|
||||
|
||||
recvPacket >> flags;
|
||||
|
||||
if(client > CLIENT_TBC)
|
||||
recvPacket >> flags;
|
||||
else
|
||||
{
|
||||
recvPacket >> flags_6005;
|
||||
flags = flags_6005;
|
||||
}
|
||||
mi.flags = 0; // not sure if its correct to set it to 0 (needs some starting flag?)
|
||||
if(flags & UPDATEFLAG_LIVING)
|
||||
{
|
||||
recvPacket >> mi.flags >> mi.unkFlags >> mi.time;
|
||||
|
||||
logdev("MovementUpdate: TypeID=%u GUID="I64FMT" pObj=%X flags=%u mi.flags=%u",objtypeid,uguid,obj,flags,mi.flags);
|
||||
|
||||
recvPacket >> mi.x >> mi.y >> mi.z >> mi.o;
|
||||
logdev("FLOATS: x=%f y=%f z=%f o=%f",mi.x, mi.y, mi.z ,mi.o);
|
||||
recvPacket >> mi;
|
||||
|
||||
logdev("MovementUpdate: TypeID=%u GUID="I64FMT" pObj=%X flags=%x mi.flags=%x",objtypeid,uguid,obj,flags,mi.flags);
|
||||
logdev("FLOATS: x=%f y=%f z=%f o=%f",mi.pos.x, mi.pos.y, mi.pos.z ,mi.pos.o);
|
||||
if(obj && obj->IsWorldObject())
|
||||
((WorldObject*)obj)->SetPosition(mi.x, mi.y, mi.z, mi.o);
|
||||
((WorldObject*)obj)->SetPosition(mi.pos.x, mi.pos.y, mi.pos.z, mi.pos.o);
|
||||
|
||||
if(mi.flags & MOVEMENTFLAG_ONTRANSPORT)
|
||||
{
|
||||
mi.t_guid = recvPacket.GetPackedGuid();
|
||||
recvPacket >> mi.t_x >> mi.t_y >> mi.t_z >> mi.t_o;
|
||||
recvPacket >> mi.t_time; // added in 2.0.3
|
||||
recvPacket >> mi.t_seat;
|
||||
logdev("TRANSPORT @ mi.flags: guid="I64FMT" x=%f y=%f z=%f o=%f", mi.t_guid, mi.t_x, mi.t_y, mi.t_z, mi.t_o);
|
||||
logdev("TRANSPORT @ mi.flags: guid="I64FMT" x=%f y=%f z=%f o=%f", mi.t_guid, mi.t_pos.x, mi.t_pos.y, mi.t_pos.z, mi.t_pos.o);
|
||||
}
|
||||
|
||||
if((mi.flags & (MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING)) || (mi.unkFlags & 0x20)) //The last one is MOVEFLAG2_ALLOW_PITCHING in MaNGOS
|
||||
if((mi.flags & (MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING)) || (mi.flags2 & MOVEMENTFLAG2_ALLOW_PITCHING))
|
||||
{
|
||||
recvPacket >> mi.s_angle;
|
||||
logdev("MovementUpdate: MOVEMENTFLAG_SWIMMING or FLYING is set, angle = %f!", mi.s_angle);
|
||||
}
|
||||
|
||||
recvPacket >> mi.fallTime;
|
||||
|
||||
logdev("MovementUpdate: FallTime = %u", mi.fallTime);
|
||||
|
||||
if(mi.flags & MOVEMENTFLAG_FALLING)
|
||||
{
|
||||
recvPacket >> mi.j_unk >> mi.j_sinAngle >> mi.j_cosAngle >> mi.j_xyspeed;
|
||||
logdev("MovementUpdate: MOVEMENTFLAG_FALLING is set, unk=%f sinA=%f cosA=%f xyspeed=%f = %u", mi.j_unk, mi.j_sinAngle, mi.j_cosAngle, mi.j_xyspeed);
|
||||
logdev("MovementUpdate: MOVEMENTFLAG_FALLING is set, velocity=%f sinA=%f cosA=%f xyspeed=%f = %u", mi.j_velocity, mi.j_sinAngle, mi.j_cosAngle, mi.j_xyspeed);
|
||||
}
|
||||
|
||||
if(mi.flags & MOVEMENTFLAG_SPLINE_ELEVATION)
|
||||
{
|
||||
recvPacket >> mi.u_unk1;
|
||||
logdev("MovementUpdate: MOVEMENTFLAG_SPLINE is set, got %u", mi.u_unk1);
|
||||
}
|
||||
|
||||
recvPacket >> speedWalk >> speedRun >> speedSwimBack >> speedSwim; // speedRun can also be mounted speed if player is mounted
|
||||
recvPacket >> speedWalkBack >> speedFly >> speedFlyBack >> speedTurn; // fly added in 2.0.x
|
||||
recvPacket >> speedPitchRate;
|
||||
recvPacket >> speedWalk >> speedRun >> speedSwimBack >> speedSwim >> speedWalkBack; // speedRun can also be mounted speed if player is mounted; WalkBack is called RunBack in Mangos
|
||||
if(client > CLIENT_CLASSIC_WOW)
|
||||
recvPacket >> speedFly >> speedFlyBack; // fly added in 2.0.x
|
||||
recvPacket >> speedTurn;
|
||||
if(client > CLIENT_TBC)
|
||||
recvPacket >> speedPitchRate;
|
||||
logdev("MovementUpdate: Got speeds, walk=%f run=%f turn=%f", speedWalk, speedRun, speedTurn);
|
||||
if(u)
|
||||
{
|
||||
u->SetPosition(mi.x, mi.y, mi.z, mi.o);
|
||||
u->SetPosition(mi.pos.x, mi.pos.y, mi.pos.z, mi.pos.o);
|
||||
u->SetSpeed(MOVE_WALK, speedWalk);
|
||||
u->SetSpeed(MOVE_RUN, speedRun);
|
||||
u->SetSpeed(MOVE_SWIMBACK, speedSwimBack);
|
||||
@ -329,7 +338,7 @@ void WorldSession::_MovementUpdate(uint8 objtypeid, uint64 uguid, WorldPacket& r
|
||||
{
|
||||
if(flags & UPDATEFLAG_POSITION)
|
||||
{
|
||||
uint64 pguid = recvPacket.GetPackedGuid();
|
||||
uint64 pguid = recvPacket.readPackGUID();
|
||||
float x,y,z,o,sx,sy,sz,so;
|
||||
recvPacket >> x >> y >> z;
|
||||
recvPacket >> sx >> sy >> sz;
|
||||
@ -358,29 +367,36 @@ void WorldSession::_MovementUpdate(uint8 objtypeid, uint64 uguid, WorldPacket& r
|
||||
}
|
||||
}
|
||||
|
||||
if(flags & UPDATEFLAG_LOWGUID)
|
||||
if(client > CLIENT_CLASSIC_WOW && flags & UPDATEFLAG_LOWGUID)
|
||||
{
|
||||
recvPacket >> unk32;
|
||||
logdev("MovementUpdate: UPDATEFLAG_LOWGUID is set, got %X", unk32);
|
||||
}
|
||||
|
||||
if(flags & UPDATEFLAG_HIGHGUID)
|
||||
if(client > CLIENT_CLASSIC_WOW && flags & UPDATEFLAG_HIGHGUID)
|
||||
{
|
||||
recvPacket >> unk32; // 2.0.6 - high guid was there, unk for 2.0.12
|
||||
// not sure if this is correct, MaNGOS sends 0 always.
|
||||
//obj->SetUInt32Value(OBJECT_FIELD_GUID+1,higuid); // note that this sets only the high part of the guid
|
||||
logdev("MovementUpdate: UPDATEFLAG_HIGHGUID is set, got %X", unk32);
|
||||
}
|
||||
if(client == CLIENT_CLASSIC_WOW && flags & UPDATEFLAG_ALL_6005)
|
||||
{
|
||||
recvPacket >> unk32;
|
||||
// MaNGOS sends 1 always.
|
||||
logdev("MovementUpdate: UPDATEFLAG_ALL is set, got %X", unk32);
|
||||
}
|
||||
|
||||
|
||||
if(flags & UPDATEFLAG_HAS_TARGET)
|
||||
{
|
||||
uint64 unkguid = recvPacket.GetPackedGuid(); // MaNGOS sends uint8(0) always, but its probably be a packed guid
|
||||
uint64 unkguid = recvPacket.readPackGUID(); // MaNGOS sends uint8(0) always, but its probably be a packed guid
|
||||
logdev("MovementUpdate: UPDATEFLAG_FULLGUID is set, got "I64FMT, unkguid);
|
||||
}
|
||||
|
||||
if(flags & UPDATEFLAG_TRANSPORT)
|
||||
{
|
||||
recvPacket >> unk32; // whats this used for?
|
||||
recvPacket >> unk32; // mangos says: ms time
|
||||
logdev("MovementUpdate: UPDATEFLAG_TRANSPORT is set, got %u", unk32);
|
||||
}
|
||||
|
||||
@ -405,8 +421,6 @@ void WorldSession::_ValuesUpdate(uint64 uguid, WorldPacket& recvPacket)
|
||||
Object *obj = objmgr.GetObj(uguid);
|
||||
uint8 blockcount,tyid;
|
||||
uint32 value, masksize, valuesCount;
|
||||
float fvalue;
|
||||
uint64 value64;
|
||||
|
||||
if(obj)
|
||||
{
|
||||
@ -431,7 +445,6 @@ void WorldSession::_ValuesUpdate(uint64 uguid, WorldPacket& recvPacket)
|
||||
umask.SetMask(updateMask);
|
||||
//delete [] updateMask; // will be deleted at ~UpdateMask() !!!!
|
||||
logdev("ValuesUpdate TypeId=%u GUID="I64FMT" pObj=%X Blocks=%u Masksize=%u",tyid,uguid,obj,blockcount,masksize);
|
||||
|
||||
// just in case the object does not exist, and we have really a container instead of an item, and a value in
|
||||
// the container fields is set, THEN we have a problem. this should never be the case; it can be fixed in a
|
||||
// more correct way if there is the need.
|
||||
@ -442,25 +455,9 @@ void WorldSession::_ValuesUpdate(uint64 uguid, WorldPacket& recvPacket)
|
||||
{
|
||||
if(obj)
|
||||
{
|
||||
if(IsFloatField(obj->GetTypeMask(),i))
|
||||
{
|
||||
recvPacket >> fvalue;
|
||||
obj->SetFloatValue(i, fvalue);
|
||||
logdev("-> Field[%u] = %f",i,fvalue);
|
||||
}
|
||||
else if(IsUInt64Field(obj->GetTypeMask(),i) && umask.GetBit(i+1))
|
||||
{
|
||||
recvPacket >> value64;
|
||||
obj->SetUInt64Value(i, value64);
|
||||
logdev("-> Field[%u] = "I64FMT,i,value64);
|
||||
i++;
|
||||
}
|
||||
else
|
||||
{
|
||||
recvPacket >> value;
|
||||
obj->SetUInt32Value(i, value);
|
||||
logdev("-> Field[%u] = %u",i,value);
|
||||
}
|
||||
recvPacket >> value;
|
||||
obj->SetUInt32Value(i, value); //It does not matter what type of value we are setting, just copy the bytes
|
||||
DEBUG(logdev("%u %u",i,value));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -525,222 +522,117 @@ void WorldSession::_QueryObjectInfo(uint64 guid)
|
||||
}
|
||||
}
|
||||
|
||||
// helper to determine if an updatefield should store float or int values, depending on TypeId
|
||||
bool IsFloatField(uint8 ty, uint32 f)
|
||||
void MovementInfo::Read(ByteBuffer &data)
|
||||
{
|
||||
static uint32 floats_object[] =
|
||||
data >> flags;
|
||||
if(_c == CLIENT_WOTLK)
|
||||
data >> flags2;
|
||||
if(_c == CLIENT_TBC)
|
||||
{
|
||||
(uint32)OBJECT_FIELD_SCALE_X,
|
||||
(uint32)-1
|
||||
};
|
||||
/*
|
||||
static uint32 floats_item[] =
|
||||
{
|
||||
(uint32)-1
|
||||
};
|
||||
static uint32 floats_container[] =
|
||||
{
|
||||
(uint32)-1
|
||||
};
|
||||
*/
|
||||
static uint32 floats_unit[] =
|
||||
{
|
||||
(uint32)UNIT_FIELD_BOUNDINGRADIUS,
|
||||
(uint32)UNIT_FIELD_COMBATREACH,
|
||||
(uint32)UNIT_FIELD_MINDAMAGE,
|
||||
(uint32)UNIT_FIELD_MAXDAMAGE,
|
||||
(uint32)UNIT_FIELD_MINOFFHANDDAMAGE,
|
||||
(uint32)UNIT_FIELD_MINOFFHANDDAMAGE,
|
||||
(uint32)UNIT_MOD_CAST_SPEED,
|
||||
(uint32)UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER,
|
||||
(uint32)UNIT_FIELD_ATTACK_POWER_MULTIPLIER,
|
||||
(uint32)UNIT_FIELD_MINRANGEDDAMAGE,
|
||||
(uint32)UNIT_FIELD_MAXRANGEDDAMAGE,
|
||||
(uint32)UNIT_FIELD_POWER_COST_MULTIPLIER,
|
||||
(uint32)UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER,
|
||||
(uint32)UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER,
|
||||
(uint32)UNIT_FIELD_MAXHEALTHMODIFIER,
|
||||
(uint32)UNIT_FIELD_HOVERHEIGHT,
|
||||
(uint32)-1
|
||||
};
|
||||
static uint32 floats_player[] =
|
||||
{
|
||||
(uint32)PLAYER_BLOCK_PERCENTAGE,
|
||||
(uint32)PLAYER_DODGE_PERCENTAGE,
|
||||
(uint32)PLAYER_PARRY_PERCENTAGE,
|
||||
(uint32)PLAYER_RANGED_CRIT_PERCENTAGE,
|
||||
(uint32)PLAYER_OFFHAND_CRIT_PERCENTAGE,
|
||||
(uint32)PLAYER_SPELL_CRIT_PERCENTAGE1,
|
||||
(uint32)PLAYER_CRIT_PERCENTAGE,
|
||||
(uint32)PLAYER_SHIELD_BLOCK_CRIT_PERCENTAGE,
|
||||
(uint32)PLAYER_FIELD_MOD_HEALING_PCT,
|
||||
(uint32)PLAYER_FIELD_MOD_HEALING_DONE_PCT,
|
||||
(uint32)PLAYER_RUNE_REGEN_1,
|
||||
(uint32)-1
|
||||
};
|
||||
static uint32 floats_gameobject[] =
|
||||
{
|
||||
(uint32)GAMEOBJECT_PARENTROTATION,
|
||||
(uint32)(GAMEOBJECT_PARENTROTATION + 1),
|
||||
(uint32)(GAMEOBJECT_PARENTROTATION + 2),
|
||||
(uint32)(GAMEOBJECT_PARENTROTATION + 3),
|
||||
(uint32)-1
|
||||
};
|
||||
static uint32 floats_dynobject[] =
|
||||
{
|
||||
(uint32)DYNAMICOBJECT_RADIUS,
|
||||
(uint32)-1
|
||||
};
|
||||
/*
|
||||
static uint32 floats_corpse[] =
|
||||
{
|
||||
(uint32)-1
|
||||
};
|
||||
*/
|
||||
uint8 tempFlags2;
|
||||
data >> tempFlags2;
|
||||
flags2 = tempFlags2;
|
||||
}
|
||||
data >> time;
|
||||
data >> pos.x;
|
||||
data >> pos.y;
|
||||
data >> pos.z;
|
||||
data >> pos.o;
|
||||
|
||||
if(ty & TYPE_OBJECT)
|
||||
for(uint32 i = 0; floats_object[i] != (uint32)(-1); i++)
|
||||
if(floats_object[i] == f)
|
||||
return true;
|
||||
/*
|
||||
if(ty & TYPE_ITEM)
|
||||
for(uint32 i = 0; floats_item[i] != (-1); i++)
|
||||
if(floats_object[i] == f)
|
||||
return true;
|
||||
if(ty & TYPE_CONTAINER)
|
||||
for(uint32 i = 0; floats_container[i] != (-1); i++)
|
||||
if(floats_object[i] == f)
|
||||
return true;
|
||||
*/
|
||||
if(ty & TYPE_UNIT)
|
||||
for(uint32 i = 0; floats_unit[i] != (uint32)(-1); i++)
|
||||
if(floats_unit[i] == f)
|
||||
return true;
|
||||
if(ty & TYPE_PLAYER)
|
||||
for(uint32 i = 0; floats_player[i] != (uint32)(-1); i++)
|
||||
if(floats_player[i] == f)
|
||||
return true;
|
||||
if(ty & TYPE_GAMEOBJECT)
|
||||
for(uint32 i = 0; floats_gameobject[i] != (uint32)(-1); i++)
|
||||
if(floats_gameobject[i] == f)
|
||||
return true;
|
||||
if(ty & TYPE_DYNAMICOBJECT)
|
||||
for(uint32 i = 0; floats_dynobject[i] != (uint32)(-1); i++)
|
||||
if(floats_dynobject[i] == f)
|
||||
return true;
|
||||
/*
|
||||
if(ty & TYPE_CORPSE)
|
||||
for(uint32 i = 0; floats_corpse[i] != (uint32)(-1); i++)
|
||||
if(floats_corpse[i] == f)
|
||||
return true;
|
||||
*/
|
||||
return false;
|
||||
if(flags & (MOVEMENTFLAG_ONTRANSPORT))
|
||||
{
|
||||
if(_c < CLIENT_WOTLK)
|
||||
data >> t_guid;
|
||||
else
|
||||
t_guid =data.readPackGUID();
|
||||
data >> t_pos.x;
|
||||
data >> t_pos.y;
|
||||
data >> t_pos.z;
|
||||
data >> t_pos.o;
|
||||
if(_c > CLIENT_CLASSIC_WOW)
|
||||
data >> t_time;
|
||||
if(_c > CLIENT_TBC)
|
||||
data >> t_seat;
|
||||
|
||||
if(_c > CLIENT_TBC && flags2 & MOVEMENTFLAG2_INTERP_MOVEMENT)
|
||||
data >> t_time2;
|
||||
}
|
||||
|
||||
if((flags & (MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING)) || (flags2 & MOVEMENTFLAG2_ALLOW_PITCHING))
|
||||
{
|
||||
data >> s_angle;
|
||||
}
|
||||
|
||||
data >> fallTime;
|
||||
|
||||
if(flags & (MOVEMENTFLAG_FALLING))
|
||||
{
|
||||
data >> j_velocity;
|
||||
data >> j_sinAngle;
|
||||
data >> j_cosAngle;
|
||||
data >> j_xyspeed;
|
||||
}
|
||||
|
||||
if(flags & (MOVEMENTFLAG_SPLINE_ELEVATION))
|
||||
{
|
||||
data >> u_unk1;
|
||||
}
|
||||
}
|
||||
|
||||
bool IsUInt64Field(uint8 ty, uint32 f)
|
||||
void MovementInfo::Write(ByteBuffer &data) const
|
||||
{
|
||||
static uint32 u64_object[] =
|
||||
data << flags;
|
||||
if(_c == CLIENT_WOTLK)
|
||||
data << flags2;
|
||||
if(_c == CLIENT_TBC)
|
||||
{
|
||||
(uint32)OBJECT_FIELD_GUID,
|
||||
(uint32)-1
|
||||
};
|
||||
|
||||
static uint32 u64_item[] =
|
||||
data << (uint8)flags2;
|
||||
}
|
||||
data << time;
|
||||
data << pos.x;
|
||||
data << pos.y;
|
||||
data << pos.z;
|
||||
data << pos.o;
|
||||
|
||||
if(flags & (MOVEMENTFLAG_ONTRANSPORT))
|
||||
{
|
||||
(uint32)ITEM_FIELD_OWNER,
|
||||
(uint32)ITEM_FIELD_CONTAINED,
|
||||
(uint32)ITEM_FIELD_CREATOR,
|
||||
(uint32)ITEM_FIELD_GIFTCREATOR,
|
||||
(uint32)-1
|
||||
};
|
||||
static uint32 u64_container[] =
|
||||
if(_c < CLIENT_WOTLK)
|
||||
data << t_guid;
|
||||
else
|
||||
data.appendPackGUID(t_guid);
|
||||
data << t_pos.x;
|
||||
data << t_pos.y;
|
||||
data << t_pos.z;
|
||||
data << t_pos.o;
|
||||
if(_c > CLIENT_CLASSIC_WOW)
|
||||
data << t_time;
|
||||
if(_c > CLIENT_TBC)
|
||||
data << t_seat;
|
||||
|
||||
if(_c > CLIENT_TBC && flags2 & MOVEMENTFLAG2_INTERP_MOVEMENT)
|
||||
data << t_time2;
|
||||
}
|
||||
|
||||
if((flags & (MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING)) || (flags2 & MOVEMENTFLAG2_ALLOW_PITCHING))
|
||||
{
|
||||
(uint32)CONTAINER_FIELD_SLOT_1,
|
||||
(uint32)-1
|
||||
};
|
||||
|
||||
static uint32 u64_unit[] =
|
||||
data << s_angle;
|
||||
}
|
||||
|
||||
data << fallTime;
|
||||
|
||||
if(flags & (MOVEMENTFLAG_FALLING))
|
||||
{
|
||||
(uint32)UNIT_FIELD_CHARM,
|
||||
(uint32)UNIT_FIELD_SUMMON,
|
||||
(uint32)UNIT_FIELD_CRITTER,
|
||||
(uint32)UNIT_FIELD_CHARMEDBY,
|
||||
(uint32)UNIT_FIELD_SUMMONEDBY,
|
||||
(uint32)UNIT_FIELD_CREATEDBY,
|
||||
(uint32)UNIT_FIELD_TARGET,
|
||||
(uint32)UNIT_FIELD_CHANNEL_OBJECT,
|
||||
(uint32)-1
|
||||
};
|
||||
static uint32 u64_player[] =
|
||||
data << j_velocity;
|
||||
data << j_sinAngle;
|
||||
data << j_cosAngle;
|
||||
data << j_xyspeed;
|
||||
}
|
||||
|
||||
if(flags & (MOVEMENTFLAG_SPLINE_ELEVATION))
|
||||
{
|
||||
(uint32)PLAYER_DUEL_ARBITER,
|
||||
(uint32)PLAYER_FIELD_INV_SLOT_HEAD,
|
||||
(uint32)PLAYER_FIELD_PACK_SLOT_1,
|
||||
(uint32)PLAYER_FIELD_BANK_SLOT_1,
|
||||
(uint32)PLAYER_FIELD_BANKBAG_SLOT_1,
|
||||
(uint32)PLAYER_FIELD_VENDORBUYBACK_SLOT_1,
|
||||
(uint32)PLAYER_FIELD_KEYRING_SLOT_1,
|
||||
(uint32)PLAYER_FIELD_CURRENCYTOKEN_SLOT_1,
|
||||
(uint32)PLAYER_FARSIGHT,
|
||||
(uint32)PLAYER__FIELD_KNOWN_TITLES,
|
||||
(uint32)PLAYER__FIELD_KNOWN_TITLES1,
|
||||
(uint32)PLAYER__FIELD_KNOWN_TITLES2,
|
||||
(uint32)PLAYER_FIELD_KNOWN_CURRENCIES,
|
||||
(uint32)-1
|
||||
};
|
||||
static uint32 u64_gameobject[] =
|
||||
{
|
||||
(uint32)OBJECT_FIELD_CREATED_BY,
|
||||
(uint32)-1
|
||||
};
|
||||
static uint32 u64_dynobject[] =
|
||||
{
|
||||
(uint32)DYNAMICOBJECT_CASTER,
|
||||
(uint32)-1
|
||||
};
|
||||
|
||||
static uint32 u64_corpse[] =
|
||||
{
|
||||
(uint32)CORPSE_FIELD_OWNER,
|
||||
(uint32)CORPSE_FIELD_PARTY,
|
||||
(uint32)-1
|
||||
};
|
||||
|
||||
if(ty & TYPE_OBJECT)
|
||||
for(uint32 i = 0; u64_object[i] != (uint32)(-1); i++)
|
||||
if(u64_object[i] == f)
|
||||
return true;
|
||||
|
||||
if(ty & TYPE_ITEM)
|
||||
for(uint32 i = 0; u64_item[i] != (uint32)(-1); i++)
|
||||
if(u64_item[i] == f)
|
||||
return true;
|
||||
if(ty & TYPE_CONTAINER)
|
||||
for(uint32 i = 0; u64_container[i] != (uint32)(-1); i++)
|
||||
if(u64_container[i] == f)
|
||||
return true;
|
||||
|
||||
if(ty & TYPE_UNIT)
|
||||
for(uint32 i = 0; u64_unit[i] != (uint32)(-1); i++)
|
||||
if(u64_unit[i] == f)
|
||||
return true;
|
||||
if(ty & TYPE_PLAYER)
|
||||
for(uint32 i = 0; u64_player[i] != (uint32)(-1); i++)
|
||||
if(u64_player[i] == f)
|
||||
return true;
|
||||
if(ty & TYPE_GAMEOBJECT)
|
||||
for(uint32 i = 0; u64_gameobject[i] != (uint32)(-1); i++)
|
||||
if(u64_gameobject[i] == f)
|
||||
return true;
|
||||
if(ty & TYPE_DYNAMICOBJECT)
|
||||
for(uint32 i = 0; u64_dynobject[i] != (uint32)(-1); i++)
|
||||
if(u64_dynobject[i] == f)
|
||||
return true;
|
||||
|
||||
if(ty & TYPE_CORPSE)
|
||||
for(uint32 i = 0; u64_corpse[i] != (uint32)(-1); i++)
|
||||
if(u64_corpse[i] == f)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
data << u_unk1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@ -26,78 +26,13 @@ enum OBJECT_UPDATE_FLAGS
|
||||
UPDATEFLAG_ROTATION = 0x0200
|
||||
};
|
||||
|
||||
enum MovementFlags
|
||||
enum OBJECT_UPDATE_FLAGS_6005 //UPDATEFLAGS with different meaning in 1.12.x
|
||||
{
|
||||
MOVEMENTFLAG_NONE = 0x00000000,
|
||||
MOVEMENTFLAG_FORWARD = 0x00000001,
|
||||
MOVEMENTFLAG_BACKWARD = 0x00000002,
|
||||
MOVEMENTFLAG_STRAFE_LEFT = 0x00000004,
|
||||
MOVEMENTFLAG_STRAFE_RIGHT = 0x00000008,
|
||||
MOVEMENTFLAG_TURN_LEFT = 0x00000010,
|
||||
MOVEMENTFLAG_TURN_RIGHT = 0x00000020,
|
||||
MOVEMENTFLAG_PITCH_UP = 0x00000040,
|
||||
MOVEMENTFLAG_PITCH_DOWN = 0x00000080,
|
||||
MOVEMENTFLAG_WALK_MODE = 0x00000100, // Walking
|
||||
MOVEMENTFLAG_ONTRANSPORT = 0x00000200,
|
||||
MOVEMENTFLAG_LEVITATING = 0x00000400,
|
||||
MOVEMENTFLAG_ROOT = 0x00000800,
|
||||
MOVEMENTFLAG_FALLING = 0x00001000,
|
||||
MOVEMENTFLAG_FALLINGFAR = 0x00002000,
|
||||
MOVEMENTFLAG_PENDINGSTOP = 0x00004000,
|
||||
MOVEMENTFLAG_PENDINGSTRAFESTOP = 0x00008000,
|
||||
MOVEMENTFLAG_PENDINGFORWARD = 0x00010000,
|
||||
MOVEMENTFLAG_PENDINGBACKWARD = 0x00020000,
|
||||
MOVEMENTFLAG_PENDINGSTRAFELEFT = 0x00040000,
|
||||
MOVEMENTFLAG_PENDINGSTRAFERIGHT = 0x00080000,
|
||||
MOVEMENTFLAG_PENDINGROOT = 0x00100000,
|
||||
MOVEMENTFLAG_SWIMMING = 0x00200000, // appears with fly flag also
|
||||
MOVEMENTFLAG_ASCENDING = 0x00400000, // swim up also
|
||||
MOVEMENTFLAG_DESCENDING = 0x00800000, // swim down also
|
||||
MOVEMENTFLAG_CAN_FLY = 0x01000000, // can fly in 3.3?
|
||||
MOVEMENTFLAG_FLYING = 0x02000000, // Actual flying mode
|
||||
MOVEMENTFLAG_SPLINE_ELEVATION = 0x04000000, // used for flight paths
|
||||
MOVEMENTFLAG_SPLINE_ENABLED = 0x08000000, // used for flight paths
|
||||
MOVEMENTFLAG_WATERWALKING = 0x10000000, // prevent unit from falling through water
|
||||
MOVEMENTFLAG_SAFE_FALL = 0x20000000, // active rogue safe fall spell (passive)
|
||||
MOVEMENTFLAG_HOVER = 0x40000000
|
||||
UPDATEFLAG_FULLGUID_6005= 0x0004,//6005 Never used in MaNGOS
|
||||
UPDATEFLAG_HIGHGUID_6005= 0x0008,//6005 Never used in MaNGOS
|
||||
UPDATEFLAG_ALL_6005 = 0x0010 //6005
|
||||
};
|
||||
|
||||
struct MovementInfo
|
||||
{
|
||||
// common
|
||||
uint32 flags;
|
||||
uint16 unkFlags;
|
||||
uint32 time;
|
||||
float x, y, z, o;
|
||||
// transport
|
||||
uint64 t_guid;
|
||||
float t_x, t_y, t_z, t_o;
|
||||
uint32 t_time;
|
||||
uint8 t_seat;
|
||||
// swimming and unk
|
||||
float s_angle;
|
||||
// last fall time
|
||||
uint32 fallTime;
|
||||
// jumping
|
||||
float j_unk, j_sinAngle, j_cosAngle, j_xyspeed;
|
||||
// spline
|
||||
float u_unk1;
|
||||
|
||||
MovementInfo()
|
||||
{
|
||||
flags = time = t_time = fallTime = unkFlags = 0;
|
||||
t_seat = 0;
|
||||
x = y = z = o = t_x = t_y = t_z = t_o = s_angle = j_unk = j_sinAngle = j_cosAngle = j_xyspeed = u_unk1 = 0.0f;
|
||||
t_guid = 0;
|
||||
}
|
||||
|
||||
void SetMovementFlags(uint32 _flags)
|
||||
{
|
||||
flags = _flags;
|
||||
}
|
||||
};
|
||||
|
||||
bool IsFloatField(uint8, uint32);
|
||||
bool IsUInt64Field(uint8, uint32);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
1118
src/Client/World/UpdateFields.cpp
Normal file
1118
src/Client/World/UpdateFields.cpp
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -19,9 +19,6 @@
|
||||
#ifndef __UPDATEMASK_H
|
||||
#define __UPDATEMASK_H
|
||||
|
||||
//#include "UpdateFields.h"
|
||||
//#include "Errors.h"
|
||||
|
||||
class UpdateMask
|
||||
{
|
||||
public:
|
||||
|
||||
@ -2,18 +2,4 @@
|
||||
#include "WorldPacket.h"
|
||||
|
||||
|
||||
uint64 WorldPacket::GetPackedGuid(void)
|
||||
{
|
||||
uint8 mask;
|
||||
*this >> mask;
|
||||
uint64 guid=0;
|
||||
for(uint8 i=0;i<8;i++)
|
||||
{
|
||||
if(mask & (1<<i) )
|
||||
{
|
||||
*this >> ((uint8*)&guid)[i];
|
||||
}
|
||||
}
|
||||
return guid;
|
||||
}
|
||||
|
||||
|
||||
@ -13,7 +13,6 @@ public:
|
||||
WorldPacket(uint16 opcode) { _opcode=opcode; reserve(10); }
|
||||
inline void SetOpcode(uint16 opcode) { _opcode=opcode; }
|
||||
inline uint16 GetOpcode(void) { return _opcode; }
|
||||
uint64 GetPackedGuid(void);
|
||||
|
||||
private:
|
||||
uint16 _opcode;
|
||||
@ -21,4 +20,4 @@ private:
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@ -15,6 +15,8 @@
|
||||
#include "RealmSession.h"
|
||||
#include "WorldSession.h"
|
||||
#include "MemoryDataHolder.h"
|
||||
#include "MovementInfo.h"
|
||||
#include "MovementMgr.h"
|
||||
|
||||
struct OpcodeHandler
|
||||
{
|
||||
@ -22,6 +24,10 @@ struct OpcodeHandler
|
||||
void (WorldSession::*handler)(WorldPacket& recvPacket);
|
||||
};
|
||||
|
||||
uint32 Object::maxvalues[TYPEID_MAX];
|
||||
UpdateField Object::updatefields[UPDATEFIELDS_NAME_COUNT];
|
||||
uint8 MovementInfo::_c=CLIENT_UNKNOWN;
|
||||
|
||||
WorldSession::WorldSession(PseuInstance *in)
|
||||
{
|
||||
logdebug("-> Starting WorldSession 0x%X from instance 0x%X",this,in); // should never output a null ptr
|
||||
@ -37,6 +43,9 @@ WorldSession::WorldSession(PseuInstance *in)
|
||||
_lag_ms = 0;
|
||||
//...
|
||||
|
||||
_SetupObjectFields();
|
||||
MovementInfo::_c=in->GetConf()->client;
|
||||
|
||||
in->GetScripts()->RunScriptIfExists("_onworldsessioncreate");
|
||||
|
||||
DEBUG(logdebug("WorldSession 0x%X constructor finished",this));
|
||||
@ -520,47 +529,62 @@ std::string WorldSession::GetOrRequestPlayerName(uint64 guid)
|
||||
|
||||
void WorldSession::_HandleAuthChallengeOpcode(WorldPacket& recvPacket)
|
||||
{
|
||||
//Read Packet
|
||||
uint32 sp, serverseed;
|
||||
if(GetInstance()->GetConf()->client > CLIENT_TBC)
|
||||
{
|
||||
recvPacket >> sp;
|
||||
}
|
||||
recvPacket >> serverseed;
|
||||
|
||||
// Do stuff with the data
|
||||
std::string acc = stringToUpper(GetInstance()->GetConf()->accname);
|
||||
uint32 sp;
|
||||
recvPacket >> sp;
|
||||
uint32 serverseed;
|
||||
recvPacket >> serverseed;
|
||||
|
||||
logdebug("Auth: serverseed=0x%X",serverseed);
|
||||
Sha1Hash digest;
|
||||
digest.UpdateData(acc);
|
||||
uint32 unk=0;
|
||||
uint64 unk64=0;
|
||||
digest.UpdateData((uint8*)&unk,sizeof(uint32));
|
||||
BigNumber clientseed;
|
||||
clientseed.SetRand(8*4);
|
||||
uint32 clientseed_uint32=clientseed.AsDword();
|
||||
digest.UpdateData((uint8*)&clientseed_uint32,sizeof(uint32));
|
||||
digest.UpdateData((uint8*)&serverseed,sizeof(uint32));
|
||||
digest.UpdateBigNumbers(GetInstance()->GetSessionKey(),NULL);
|
||||
digest.Finalize();
|
||||
WorldPacket auth;
|
||||
auth<<(uint32)(GetInstance()->GetConf()->clientbuild)<<unk<<acc<<unk<<clientseed_uint32<<unk<<unk<<unk<<unk64;
|
||||
auth.append(digest.GetDigest(),20);
|
||||
auth << (uint32)0; // TODO: this is not correct value, expected: 160 bytes of addon_data
|
||||
logdebug("Auth: serverseed=0x%X",serverseed);
|
||||
Sha1Hash digest;
|
||||
digest.UpdateData(acc);
|
||||
uint32 unk=0;
|
||||
uint64 unk64=0;
|
||||
digest.UpdateData((uint8*)&unk,sizeof(uint32));
|
||||
BigNumber clientseed;
|
||||
clientseed.SetRand(8*4);
|
||||
uint32 clientseed_uint32=clientseed.AsDword();
|
||||
digest.UpdateData((uint8*)&clientseed_uint32,sizeof(uint32));
|
||||
digest.UpdateData((uint8*)&serverseed,sizeof(uint32));
|
||||
digest.UpdateBigNumbers(GetInstance()->GetSessionKey(),NULL);
|
||||
digest.Finalize();
|
||||
|
||||
// Send Reply
|
||||
WorldPacket auth;
|
||||
if(GetInstance()->GetConf()->client<=CLIENT_TBC)
|
||||
{
|
||||
auth<<(uint32)(GetInstance()->GetConf()->clientbuild)<<unk<<acc<<clientseed_uint32;
|
||||
auth.append(digest.GetDigest(),20);
|
||||
}
|
||||
else
|
||||
{
|
||||
auth<<(uint32)(GetInstance()->GetConf()->clientbuild)<<unk<<acc<<unk<<clientseed_uint32<<unk<<unk<<unk<<unk64;
|
||||
auth.append(digest.GetDigest(),20);
|
||||
}
|
||||
auth << (uint32)0; // TODO: this is not correct value, expected: 160 bytes of addon_data
|
||||
auth.SetOpcode(CMSG_AUTH_SESSION);
|
||||
|
||||
auth.SetOpcode(CMSG_AUTH_SESSION);
|
||||
SendWorldPacket(auth);
|
||||
|
||||
SendWorldPacket(auth);
|
||||
|
||||
// note that if the sessionkey/auth is wrong or failed, the server sends the following packet UNENCRYPTED!
|
||||
// so its not 100% correct to init the crypt here, but it should do the job if authing was correct
|
||||
_socket->InitCrypt(GetInstance()->GetSessionKey());
|
||||
// note that if the sessionkey/auth is wrong or failed, the server sends the following packet UNENCRYPTED!
|
||||
// so its not 100% correct to init the crypt here, but it should do the job if authing was correct
|
||||
_socket->InitCrypt(GetInstance()->GetSessionKey());
|
||||
|
||||
}
|
||||
|
||||
void WorldSession::_HandleAuthResponseOpcode(WorldPacket& recvPacket)
|
||||
{
|
||||
uint8 errcode;
|
||||
uint8 dummy8, expansion; uint32 dummy32;
|
||||
uint8 BillingPlanFlags, expansion; uint32 BillingTimeRemaining, BillingTimeRested;
|
||||
recvPacket >> errcode;
|
||||
recvPacket >> dummy32 >> dummy8 >> dummy32;
|
||||
recvPacket >> expansion;
|
||||
recvPacket >> BillingTimeRemaining >> BillingPlanFlags >> BillingTimeRested;
|
||||
if(GetInstance()->GetConf()->client > CLIENT_CLASSIC_WOW)
|
||||
recvPacket >> expansion;
|
||||
// TODO: add data to generic_text.scp and use the strings here
|
||||
if(errcode == AUTH_OK)
|
||||
{
|
||||
@ -570,7 +594,7 @@ void WorldSession::_HandleAuthResponseOpcode(WorldPacket& recvPacket)
|
||||
}
|
||||
else
|
||||
{
|
||||
logerror("World Authentication failed, errcode=0x%X",(unsigned char)errcode);
|
||||
logerror("World Authentication failed, errcode=0x%X",(uint8)errcode);
|
||||
SetMustDie();
|
||||
}
|
||||
}
|
||||
@ -604,11 +628,11 @@ void WorldSession::_HandleCharEnumOpcode(WorldPacket& recvPacket)
|
||||
recvPacket >> plr[i]._race;
|
||||
recvPacket >> plr[i]._class;
|
||||
recvPacket >> plr[i]._gender;
|
||||
recvPacket >> plr[i]._bytes1;
|
||||
recvPacket >> plr[i]._bytes2;
|
||||
recvPacket >> plr[i]._bytes3;
|
||||
recvPacket >> plr[i]._bytes4;
|
||||
recvPacket >> plr[i]._bytesx;
|
||||
recvPacket >> plr[i]._bytes1;//skin
|
||||
recvPacket >> plr[i]._bytes2;//face
|
||||
recvPacket >> plr[i]._bytes3;//hair style
|
||||
recvPacket >> plr[i]._bytes4;//hair color
|
||||
recvPacket >> plr[i]._bytesx;//facial hair
|
||||
recvPacket >> plr[i]._level;
|
||||
recvPacket >> plr[i]._zoneId;
|
||||
recvPacket >> plr[i]._mapId;
|
||||
@ -617,14 +641,21 @@ void WorldSession::_HandleCharEnumOpcode(WorldPacket& recvPacket)
|
||||
recvPacket >> plr[i]._z;
|
||||
recvPacket >> plr[i]._guildId;
|
||||
recvPacket >> plr[i]._flags;
|
||||
recvPacket >> dummy32; // at_login_customize
|
||||
if(GetInstance()->GetConf()->client > CLIENT_TBC)
|
||||
{
|
||||
recvPacket >> dummy32; // at_login_customize
|
||||
}
|
||||
recvPacket >> dummy8;
|
||||
recvPacket >> plr[i]._petInfoId;
|
||||
recvPacket >> plr[i]._petLevel;
|
||||
recvPacket >> plr[i]._petFamilyId;
|
||||
for(unsigned int inv=0;inv<20;inv++)
|
||||
{
|
||||
recvPacket >> plr[i]._items[inv].displayId >> plr[i]._items[inv].inventorytype >> dummy32;
|
||||
recvPacket >> plr[i]._items[inv].displayId >> plr[i]._items[inv].inventorytype ;
|
||||
if(GetInstance()->GetConf()->client > CLIENT_CLASSIC_WOW)
|
||||
{
|
||||
recvPacket >> dummy32; //enchant aura id
|
||||
}
|
||||
}
|
||||
plrNameCache.Add(plr[i]._guid, plr[i]._name); // TODO: set after loadingscreen, after loading cache
|
||||
|
||||
@ -811,7 +842,7 @@ void WorldSession::_HandleAccountDataMD5Opcode(WorldPacket& recvPacket)
|
||||
// packet structure not yet known
|
||||
}
|
||||
|
||||
void WorldSession::_HandleMessageChatOpcode(WorldPacket& recvPacket)
|
||||
void WorldSession::_HandleMessageChatOpcode(WorldPacket& recvPacket) //TODO: REWRITE ME!!!
|
||||
{
|
||||
uint8 type, chatTag;
|
||||
uint32 lang;
|
||||
@ -826,9 +857,11 @@ void WorldSession::_HandleMessageChatOpcode(WorldPacket& recvPacket)
|
||||
|
||||
if(lang == LANG_ADDON && GetInstance()->GetConf()->skipaddonchat)
|
||||
return;
|
||||
|
||||
recvPacket >> source_guid;
|
||||
recvPacket >> unk32;
|
||||
if(GetInstance()->GetConf()->client > CLIENT_CLASSIC_WOW)
|
||||
{
|
||||
recvPacket >> source_guid;
|
||||
recvPacket >> unk32;
|
||||
}
|
||||
|
||||
switch(type)
|
||||
{
|
||||
@ -1016,13 +1049,19 @@ void WorldSession::_HandleNotificationOpcode(WorldPacket& recvPacket)
|
||||
void WorldSession::_HandleNameQueryResponseOpcode(WorldPacket& recvPacket)
|
||||
{
|
||||
uint64 pguid;
|
||||
uint8 unk;
|
||||
uint8 realm;
|
||||
std::string pname;
|
||||
|
||||
pguid = recvPacket.GetPackedGuid();
|
||||
recvPacket >> unk >> pname;
|
||||
uint32 prace, pgender, pclass;
|
||||
if(GetInstance()->GetConf()->client > CLIENT_CLASSIC_WOW)
|
||||
pguid = recvPacket.readPackGUID();
|
||||
else
|
||||
recvPacket >> pguid;
|
||||
recvPacket >> pname >> realm >> prace >> pgender >> pclass;
|
||||
if(pname.length()>MAX_PLAYERNAME_LENGTH || pname.length()<MIN_PLAYERNAME_LENGTH)
|
||||
{
|
||||
logerror("Playername Length outside bounds: %u",pname.length());
|
||||
return; // playernames maxlen=12, minlen=2
|
||||
}
|
||||
// rest of the packet is not interesting for now
|
||||
plrNameCache.Add(pguid,pname);
|
||||
logdetail("CACHE: Assigned new player name: '%s' = " I64FMTD ,pname.c_str(),pguid);
|
||||
@ -1064,27 +1103,26 @@ void WorldSession::_HandleGroupInviteOpcode(WorldPacket& recvPacket)
|
||||
|
||||
void WorldSession::_HandleMovementOpcode(WorldPacket& recvPacket)
|
||||
{
|
||||
uint32 flags, time, unk32;
|
||||
float x, y, z, o;
|
||||
uint64 guid;
|
||||
uint16 flags2;
|
||||
guid = recvPacket.GetPackedGuid();
|
||||
recvPacket >> flags >> flags2 >> time >> x >> y >> z >> o >> unk32;
|
||||
DEBUG(logdebug("MOVE: "I64FMT" -> time=%u flags=0x%X x=%.4f y=%.4f z=%.4f o=%.4f",guid,time,flags,x,y,z,o));
|
||||
MovementInfo mi;
|
||||
guid = recvPacket.readPackGUID();
|
||||
recvPacket >> mi;
|
||||
DEBUG(logdebug("MOVE: "I64FMT" -> time=%u flags=0x%X x=%.4f y=%.4f z=%.4f o=%.4f",guid,mi.time,mi.flags,mi.pos.x,mi.pos.y,mi.pos.z,mi.pos.o));
|
||||
Object *obj = objmgr.GetObj(guid);
|
||||
if(obj && obj->IsWorldObject())
|
||||
{
|
||||
((WorldObject*)obj)->SetPosition(x,y,z,o);
|
||||
((WorldObject*)obj)->SetPosition(mi.pos.x,mi.pos.y,mi.pos.z,mi.pos.o);
|
||||
}
|
||||
//TODO: Eval rest of Packet!!
|
||||
}
|
||||
|
||||
void WorldSession::_HandleSetSpeedOpcode(WorldPacket& recvPacket)
|
||||
{
|
||||
uint64 guid;
|
||||
float x, y, z, o, speed;
|
||||
uint32 unk32, movetype;
|
||||
uint16 unk16;
|
||||
|
||||
float speed;
|
||||
uint32 movetype;
|
||||
MovementInfo mi;
|
||||
|
||||
switch(recvPacket.GetOpcode())
|
||||
{
|
||||
case MSG_MOVE_SET_WALK_SPEED:
|
||||
@ -1128,19 +1166,15 @@ void WorldSession::_HandleSetSpeedOpcode(WorldPacket& recvPacket)
|
||||
return;
|
||||
}
|
||||
|
||||
guid = recvPacket.GetPackedGuid();
|
||||
recvPacket >> unk32;
|
||||
recvPacket >> unk16;
|
||||
recvPacket >> unk32; /* getMSTime()*/
|
||||
recvPacket >> x >> y >> z >> o;
|
||||
recvPacket >> unk32; // falltime
|
||||
guid = recvPacket.readPackGUID();
|
||||
recvPacket >> mi;
|
||||
recvPacket >> speed;
|
||||
|
||||
Object *obj = objmgr.GetObj(guid);
|
||||
if(obj && obj->IsUnit())
|
||||
{
|
||||
((Unit*)obj)->SetSpeed(movetype, speed);
|
||||
((Unit*)obj)->SetPosition(x, y, z, o);
|
||||
((Unit*)obj)->SetPosition(mi.pos.x, mi.pos.y, mi.pos.z, mi.pos.o);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1194,7 +1228,7 @@ void WorldSession::_HandleForceSetSpeedOpcode(WorldPacket& recvPacket)
|
||||
return;
|
||||
}
|
||||
|
||||
guid = recvPacket.GetPackedGuid();
|
||||
guid = recvPacket.readPackGUID();
|
||||
recvPacket >> unk32;
|
||||
if (movetype == MOVE_RUN)
|
||||
recvPacket >> unk8;
|
||||
@ -1209,47 +1243,44 @@ void WorldSession::_HandleForceSetSpeedOpcode(WorldPacket& recvPacket)
|
||||
|
||||
void WorldSession::_HandleTelePortAckOpcode(WorldPacket& recvPacket)
|
||||
{
|
||||
uint32 unk32,time, flags; // movement flags
|
||||
uint32 unk32;
|
||||
uint64 guid;
|
||||
uint16 unk16;
|
||||
float x, y, z, o;
|
||||
MovementInfo mi;
|
||||
guid = recvPacket.readPackGUID();
|
||||
recvPacket >> unk32 >> mi;
|
||||
|
||||
guid = recvPacket.GetPackedGuid();
|
||||
recvPacket >> unk32 >> flags >> unk16 >> time >> x >> y >> z >> o >> unk32;
|
||||
logdetail("Got teleported, data: x: %f, y: %f, z: %f, o: %f, guid: "I64FMT, mi.pos.x, mi.pos.y, mi.pos.z, mi.pos.o, guid);
|
||||
|
||||
logdetail("Got teleported, data: x: %f, y: %f, z: %f, o: %f, guid: "I64FMT, x, y, z, o, guid);
|
||||
|
||||
WorldPacket wp(MSG_MOVE_TELEPORT_ACK,8+4+4);
|
||||
//GUID must be packed!
|
||||
wp.appendPackGUID(guid);
|
||||
wp << (uint32)0 << (uint32)getMSTime();
|
||||
SendWorldPacket(wp);
|
||||
|
||||
// TODO: put this into a capsule class later, that autodetects movement flags etc.
|
||||
WorldPacket response(MSG_MOVE_FALL_LAND,4+2+4+4+4+4+4+4);
|
||||
response.appendPackGUID(guid);
|
||||
response << uint32(0) << (uint16)0 << (uint32)getMSTime(); //flags and flags2
|
||||
response << x << y << z << o << uint32(100); // simulate 100 msec fall time
|
||||
SendWorldPacket(response);
|
||||
|
||||
_world->UpdatePos(x,y);
|
||||
_world->UpdatePos(mi.pos.x,mi.pos.y);
|
||||
_world->Update();
|
||||
|
||||
if(MyCharacter *my = GetMyChar())
|
||||
{
|
||||
my->SetPosition(x,y,z,o);
|
||||
my->SetPosition(mi.pos.x,mi.pos.y,mi.pos.z,mi.pos.o);
|
||||
}
|
||||
|
||||
WorldPacket wp(MSG_MOVE_TELEPORT_ACK,8+4+4);
|
||||
if(GetInstance()->GetConf()->client > CLIENT_TBC)
|
||||
wp.appendPackGUID(guid); //GUID must be packed!
|
||||
else
|
||||
wp << guid;
|
||||
wp << (uint32)0 << (uint32)getMSTime(); //First value is some counter
|
||||
SendWorldPacket(wp);
|
||||
|
||||
_world->GetMoveMgr()->SetFallTime(100);
|
||||
_world->GetMoveMgr()->MoveFallLand();
|
||||
|
||||
|
||||
if(GetInstance()->GetScripts()->ScriptExists("_onteleport"))
|
||||
{
|
||||
CmdSet Set;
|
||||
Set.defaultarg = "false"; // teleported to other map = false
|
||||
Set.arg[0] = DefScriptTools::toString(guid);
|
||||
Set.arg[1] = DefScriptTools::toString(x);
|
||||
Set.arg[2] = DefScriptTools::toString(y);
|
||||
Set.arg[3] = DefScriptTools::toString(z);
|
||||
Set.arg[4] = DefScriptTools::toString(o);
|
||||
Set.arg[5] = DefScriptTools::toString(flags);
|
||||
Set.arg[1] = DefScriptTools::toString(mi.pos.x);
|
||||
Set.arg[2] = DefScriptTools::toString(mi.pos.y);
|
||||
Set.arg[3] = DefScriptTools::toString(mi.pos.z);
|
||||
Set.arg[4] = DefScriptTools::toString(mi.pos.o);
|
||||
Set.arg[5] = DefScriptTools::toString(mi.flags);
|
||||
GetInstance()->GetScripts()->RunScriptIfExists("_onteleport");
|
||||
}
|
||||
}
|
||||
@ -1276,12 +1307,6 @@ void WorldSession::_HandleNewWorldOpcode(WorldPacket& recvPacket)
|
||||
wp << GetGuid();
|
||||
SendWorldPacket(wp);
|
||||
|
||||
// TODO: put this into a capsule class later, that autodetects movement flags etc.
|
||||
WorldPacket response(MSG_MOVE_FALL_LAND,4+2+4+4+4+4+4+4);
|
||||
response << uint32(0) << (uint16)0; // no flags; unk
|
||||
response <<(uint32)getMSTime(); // time correct?
|
||||
response << x << y << z << o << uint32(100); // simulate 100 msec fall time
|
||||
SendWorldPacket(response);
|
||||
|
||||
|
||||
|
||||
@ -1297,6 +1322,9 @@ void WorldSession::_HandleNewWorldOpcode(WorldPacket& recvPacket)
|
||||
my->ClearSpells(); // will be resent by server
|
||||
my->SetPosition(x,y,z,o,mapid);
|
||||
}
|
||||
|
||||
_world->GetMoveMgr()->SetFallTime(100);
|
||||
_world->GetMoveMgr()->MoveFallLand();//Must be sent after character was set to new position
|
||||
|
||||
// TODO: need to switch to SCENESTATE_LOGINSCREEN here, and after everything is loaded, back to SCENESTATE_WORLD
|
||||
|
||||
@ -1333,7 +1361,7 @@ void WorldSession::_HandleCastSuccessOpcode(WorldPacket& recvPacket)
|
||||
uint32 spellId;
|
||||
uint64 casterGuid;
|
||||
|
||||
casterGuid = recvPacket.GetPackedGuid();
|
||||
casterGuid = recvPacket.readPackGUID();
|
||||
recvPacket >> spellId;
|
||||
|
||||
if (GetMyChar()->GetGUID() == casterGuid)
|
||||
@ -1351,16 +1379,31 @@ void WorldSession::_HandleCastSuccessOpcode(WorldPacket& recvPacket)
|
||||
void WorldSession::_HandleInitialSpellsOpcode(WorldPacket& recvPacket)
|
||||
{
|
||||
uint8 unk;
|
||||
uint16 spellslot,count;
|
||||
uint16 not_spellslot,count,spellid16;
|
||||
uint32 spellid;
|
||||
recvPacket >> unk >> count;
|
||||
logdebug("Got initial spells list, %u spells.",count);
|
||||
for(uint16 i = 0; i < count; i++)
|
||||
if(GetInstance()->GetConf()->client > CLIENT_TBC)
|
||||
{
|
||||
recvPacket >> spellid >> spellslot;
|
||||
logdebug("Initial Spell: id=%u slot=%u",spellid,spellslot);
|
||||
GetMyChar()->AddSpell(spellid, spellslot);
|
||||
for(uint16 i = 0; i < count; i++)
|
||||
{
|
||||
recvPacket >> spellid >> not_spellslot;
|
||||
logdebug("Initial Spell: id=%u slot=%u",spellid,not_spellslot);
|
||||
GetMyChar()->AddSpell(spellid, not_spellslot);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(uint16 i = 0; i < count; i++)
|
||||
{
|
||||
recvPacket >> spellid16 >> not_spellslot;
|
||||
spellid = spellid16;
|
||||
logdebug("Initial Spell: id=%u slot=%u",spellid,not_spellslot);
|
||||
GetMyChar()->AddSpell(spellid, not_spellslot);
|
||||
}
|
||||
|
||||
}
|
||||
//TODO: Parse packet completely
|
||||
}
|
||||
|
||||
void WorldSession::_HandleLearnedSpellOpcode(WorldPacket& recvPacket)
|
||||
@ -1612,7 +1655,7 @@ void WorldSession::_HandleCreatureQueryResponseOpcode(WorldPacket& recvPacket)
|
||||
|
||||
CreatureTemplate *ct = new CreatureTemplate();
|
||||
std::string s;
|
||||
//uint32 unk;
|
||||
uint32 unk;
|
||||
float unkf;
|
||||
ct->entry = entry;
|
||||
recvPacket >> ct->name;
|
||||
@ -1620,24 +1663,43 @@ void WorldSession::_HandleCreatureQueryResponseOpcode(WorldPacket& recvPacket)
|
||||
recvPacket >> s;
|
||||
recvPacket >> s;
|
||||
recvPacket >> ct->subname;
|
||||
recvPacket >> ct->directions;
|
||||
if(GetInstance()->GetConf()->client > CLIENT_CLASSIC_WOW)
|
||||
recvPacket >> ct->directions;
|
||||
recvPacket >> ct->flag1;
|
||||
recvPacket >> ct->type;
|
||||
recvPacket >> ct->family;
|
||||
recvPacket >> ct->rank;
|
||||
for(uint32 i = 0; i < MAX_KILL_CREDIT; i++)
|
||||
recvPacket >> ct->killCredit[i];
|
||||
recvPacket >> ct->displayid_A;
|
||||
recvPacket >> ct->displayid_H;
|
||||
recvPacket >> ct->displayid_AF;
|
||||
recvPacket >> ct->displayid_HF;
|
||||
recvPacket >> unkf;
|
||||
recvPacket >> unkf;
|
||||
recvPacket >> ct->RacialLeader;
|
||||
for(uint32 i = 0; i < 4; i++)
|
||||
recvPacket >> ct->questItems[i];
|
||||
recvPacket >> ct->movementId;
|
||||
|
||||
if(GetInstance()->GetConf()->client > CLIENT_CLASSIC_WOW)
|
||||
{
|
||||
if(GetInstance()->GetConf()->client == CLIENT_WOTLK)
|
||||
{
|
||||
for(uint32 i = 0; i < MAX_KILL_CREDIT; i++)
|
||||
recvPacket >> ct->killCredit[i];
|
||||
}
|
||||
recvPacket >> ct->displayid_A;
|
||||
recvPacket >> ct->displayid_H;
|
||||
recvPacket >> ct->displayid_AF;
|
||||
recvPacket >> ct->displayid_HF;
|
||||
recvPacket >> unkf;
|
||||
recvPacket >> unkf;
|
||||
recvPacket >> ct->RacialLeader;
|
||||
if(GetInstance()->GetConf()->client == CLIENT_WOTLK)
|
||||
{
|
||||
for(uint32 i = 0; i < 4; i++)
|
||||
recvPacket >> ct->questItems[i];
|
||||
recvPacket >> ct->movementId;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
recvPacket >> unk;
|
||||
recvPacket >> ct->PetSpellDataId;
|
||||
recvPacket >> ct->displayid_A;
|
||||
ct->displayid_H = ct->displayid_A;
|
||||
ct->displayid_AF = ct->displayid_A;
|
||||
ct->displayid_HF = ct->displayid_A;
|
||||
recvPacket >> ct->civilian;
|
||||
}
|
||||
std::stringstream ss;
|
||||
ss << "Got info for creature " << entry << ":" << ct->name;
|
||||
if(!ct->subname.empty())
|
||||
@ -1673,15 +1735,23 @@ void WorldSession::_HandleGameobjectQueryResponseOpcode(WorldPacket& recvPacket)
|
||||
recvPacket >> other_names; // name1
|
||||
recvPacket >> other_names; // name2
|
||||
recvPacket >> other_names; // name3 (all unused)
|
||||
recvPacket >> unks;
|
||||
recvPacket >> go->castBarCaption;
|
||||
recvPacket >> go->unk1;
|
||||
if(GetInstance()->GetConf()->client > CLIENT_CLASSIC_WOW)
|
||||
{
|
||||
recvPacket >> unks;
|
||||
recvPacket >> go->castBarCaption;
|
||||
recvPacket >> go->unk1;
|
||||
}
|
||||
for(uint32 i = 0; i < GAMEOBJECT_DATA_FIELDS; i++)
|
||||
recvPacket >> go->raw.data[i];
|
||||
recvPacket >> go->size;
|
||||
for(uint32 i = 0; i < 4; i++)
|
||||
recvPacket >> go->questItems[i];
|
||||
|
||||
if(GetInstance()->GetConf()->client > CLIENT_CLASSIC_WOW)
|
||||
{
|
||||
recvPacket >> go->size;
|
||||
if(GetInstance()->GetConf()->client > CLIENT_TBC)
|
||||
{
|
||||
for(uint32 i = 0; i < 4; i++)
|
||||
recvPacket >> go->questItems[i];
|
||||
}
|
||||
}
|
||||
std::stringstream ss;
|
||||
ss << "Got info for gameobject " << entry << ":" << go->name;
|
||||
ss << " type " << go->type;
|
||||
@ -1723,7 +1793,7 @@ void WorldSession::_HandleCharCreateOpcode(WorldPacket& recvPacket)
|
||||
void WorldSession::_HandleMonsterMoveOpcode(WorldPacket& recvPacket)
|
||||
{
|
||||
uint64 guid;
|
||||
guid = recvPacket.GetPackedGuid();
|
||||
guid = recvPacket.readPackGUID();
|
||||
|
||||
Object* obj = objmgr.GetObj(guid);
|
||||
if (!obj || !obj->IsWorldObject())
|
||||
@ -1732,7 +1802,10 @@ void WorldSession::_HandleMonsterMoveOpcode(WorldPacket& recvPacket)
|
||||
uint8 unk, type;
|
||||
uint32 time, flags, movetime, waypoints;
|
||||
float x, y, z;
|
||||
recvPacket >> unk >> x >> y >> z >> time >> type;
|
||||
if(GetInstance()->GetConf()->client > CLIENT_TBC)
|
||||
recvPacket >> unk;
|
||||
|
||||
recvPacket >> x >> y >> z >> time >> type;
|
||||
|
||||
float oldx = ((WorldObject*)obj)->GetX(),
|
||||
oldy = ((WorldObject*)obj)->GetY();
|
||||
|
||||
@ -126,6 +126,7 @@ private:
|
||||
void _DoTimedActions(void);
|
||||
void _DelayWorldPacket(WorldPacket&, uint32);
|
||||
void _HandleDelayedPackets(void);
|
||||
void _SetupObjectFields(void);
|
||||
|
||||
// Opcode Handlers
|
||||
void _HandleAuthChallengeOpcode(WorldPacket& recvPacket);
|
||||
|
||||
@ -4,11 +4,17 @@
|
||||
#include "WorldSocket.h"
|
||||
#include "Opcodes.h"
|
||||
|
||||
|
||||
|
||||
WorldSocket::WorldSocket(SocketHandler &h, WorldSession *s) : TcpSocket(h)
|
||||
{
|
||||
_session = s;
|
||||
_gothdr = false;
|
||||
_ok=false;
|
||||
|
||||
//Dummy functions for unencrypted packets on WorldSocket
|
||||
pDecryptRecv = &AuthCrypt::DecryptRecvDummy;
|
||||
pEncryptSend = &AuthCrypt::EncryptSendDummy;
|
||||
}
|
||||
|
||||
bool WorldSocket::IsOk(void)
|
||||
@ -78,31 +84,43 @@ void WorldSocket::OnRead()
|
||||
break;
|
||||
}
|
||||
|
||||
// read first byte and check if size is 3 or 2 bytes
|
||||
uint8 firstSizeByte;
|
||||
ibuf.Read((char*)&firstSizeByte, 1);
|
||||
_crypt.DecryptRecv(&firstSizeByte, 1);
|
||||
|
||||
if (firstSizeByte & 0x80) // got large packet
|
||||
if(GetSession()->GetInstance()->GetConf()->client > CLIENT_TBC)//Funny, old sources have this in TBC already...
|
||||
{
|
||||
ServerPktHeaderBig hdr;
|
||||
ibuf.Read(((char*)&hdr) + 1, sizeof(ServerPktHeaderBig) - 1); // read *big* header, except first byte
|
||||
_crypt.DecryptRecv(((uint8*)&hdr) + 1, sizeof(ServerPktHeaderBig) - 1); // decrypt 2 of 3 bytes (first one already decrypted above) of size, and cmd
|
||||
hdr.size[0] = firstSizeByte; // assign missing first byte
|
||||
// read first byte and check if size is 3 or 2 bytes
|
||||
uint8 firstSizeByte;
|
||||
ibuf.Read((char*)&firstSizeByte, 1);
|
||||
(_crypt.*pDecryptRecv)(&firstSizeByte, 1);
|
||||
if (firstSizeByte & 0x80) // got large packet
|
||||
{
|
||||
ServerPktHeaderBig hdr;
|
||||
ibuf.Read(((char*)&hdr) + 1, sizeof(ServerPktHeaderBig) - 1); // read *big* header, except first byte
|
||||
(_crypt.*pDecryptRecv)(((uint8*)&hdr) + 1, sizeof(ServerPktHeaderBig) - 1); // decrypt 2 of 3 bytes (first one already decrypted above) of size, and cmd
|
||||
hdr.size[0] = firstSizeByte; // assign missing first byte
|
||||
|
||||
uint32 realsize = ((hdr.size[0]&0x7F) << 16) | (hdr.size[1] << 8) | hdr.size[2];
|
||||
_remaining = realsize - 2;
|
||||
_opcode = hdr.cmd;
|
||||
uint32 realsize = ((hdr.size[0]&0x7F) << 16) | (hdr.size[1] << 8) | hdr.size[2];
|
||||
_remaining = realsize - 2;
|
||||
_opcode = hdr.cmd;
|
||||
}
|
||||
else // "normal" packet
|
||||
{
|
||||
ServerPktHeader hdr;
|
||||
ibuf.Read(((char*)&hdr) + 1, sizeof(ServerPktHeader) - 1); // read header, except first byte
|
||||
(_crypt.*pDecryptRecv)(((uint8*)&hdr) + 1, sizeof(ServerPktHeader) - 1); // decrypt all except first
|
||||
hdr.size |= firstSizeByte; // add already decrypted first byte
|
||||
|
||||
_remaining = ntohs(hdr.size) - 2;
|
||||
_opcode = hdr.cmd;
|
||||
}
|
||||
}
|
||||
else // "normal" packet
|
||||
else
|
||||
{
|
||||
ServerPktHeader hdr;
|
||||
ibuf.Read(((char*)&hdr) + 1, sizeof(ServerPktHeader) - 1); // read header, except first byte
|
||||
_crypt.DecryptRecv(((uint8*)&hdr) + 1, sizeof(ServerPktHeader) - 1); // decrypt all except first
|
||||
hdr.size |= firstSizeByte; // add already decrypted first byte
|
||||
ServerPktHeader hdr;
|
||||
ibuf.Read(((char*)&hdr), sizeof(ServerPktHeader)); // read header
|
||||
(_crypt.*pDecryptRecv)(((uint8*)&hdr), sizeof(ServerPktHeader)); // decrypt all
|
||||
|
||||
_remaining = ntohs(hdr.size) - 2;
|
||||
_opcode = hdr.cmd;
|
||||
_remaining = ntohs(hdr.size) - 2;
|
||||
_opcode = hdr.cmd;
|
||||
|
||||
}
|
||||
|
||||
if(_opcode > MAX_OPCODE_ID)
|
||||
@ -114,7 +132,6 @@ void WorldSocket::OnRead()
|
||||
// TODO: invent some way how to recover the crypt (reconnect?)
|
||||
return;
|
||||
}
|
||||
|
||||
// the header is fine, now check if there are more data
|
||||
if(_remaining == 0) // this is a packet with no data (like CMSG_NULL_ACTION)
|
||||
{
|
||||
@ -138,7 +155,7 @@ void WorldSocket::SendWorldPacket(WorldPacket &pkt)
|
||||
memset(&hdr,0,sizeof(ClientPktHeader));
|
||||
hdr.size = ntohs(pkt.size()+4);
|
||||
hdr.cmd = pkt.GetOpcode();
|
||||
_crypt.EncryptSend((uint8*)&hdr, 6);
|
||||
(_crypt.*pEncryptSend)((uint8*)&hdr, 6);
|
||||
ByteBuffer final(pkt.size()+6);
|
||||
final.append((uint8*)&hdr,sizeof(ClientPktHeader));
|
||||
if(pkt.size())
|
||||
@ -148,7 +165,38 @@ void WorldSocket::SendWorldPacket(WorldPacket &pkt)
|
||||
|
||||
void WorldSocket::InitCrypt(BigNumber *k)
|
||||
{
|
||||
_crypt.Init(k);
|
||||
//As crypt
|
||||
switch(GetSession()->GetInstance()->GetConf()->client)
|
||||
{
|
||||
case CLIENT_CLASSIC_WOW:
|
||||
{
|
||||
logdebug("Setting Crypt to Build 6005");
|
||||
pInit = &AuthCrypt::Init_6005;
|
||||
pDecryptRecv = &AuthCrypt::DecryptRecv_6005;
|
||||
pEncryptSend = &AuthCrypt::EncryptSend_6005;
|
||||
break;
|
||||
}
|
||||
case CLIENT_TBC:
|
||||
{
|
||||
logdebug("Setting Crypt to Build 8606");
|
||||
pInit = &AuthCrypt::Init_8606;
|
||||
pDecryptRecv = &AuthCrypt::DecryptRecv_6005;
|
||||
pEncryptSend = &AuthCrypt::EncryptSend_6005;
|
||||
break;
|
||||
}
|
||||
case CLIENT_WOTLK:
|
||||
{
|
||||
logdebug("Setting Crypt to Build 12340");
|
||||
pInit = &AuthCrypt::Init_12340;
|
||||
pDecryptRecv = &AuthCrypt::DecryptRecv_12340;
|
||||
pEncryptSend = &AuthCrypt::EncryptSend_12340;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
logerror("Error setting up Crypt - will crash now (check conf)");
|
||||
break;
|
||||
}
|
||||
(_crypt.*pInit)(k);
|
||||
const char *hexstr = k->AsHexStr();
|
||||
logdebug("WorldSocket: Crypt initialized [%s]",hexstr);
|
||||
OPENSSL_free((void*)hexstr);
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
class WorldSession;
|
||||
class BigNumber;
|
||||
|
||||
|
||||
#if defined( __GNUC__ )
|
||||
#pragma pack(1)
|
||||
#else
|
||||
@ -60,6 +61,9 @@ public:
|
||||
private:
|
||||
WorldSession *_session;
|
||||
AuthCrypt _crypt;
|
||||
void (AuthCrypt::*pInit)(BigNumber *);
|
||||
void (AuthCrypt::*pDecryptRecv)(uint8 *, size_t);
|
||||
void (AuthCrypt::*pEncryptSend)(uint8 *, size_t);
|
||||
bool _gothdr; // true if only the header was recieved yet
|
||||
uint16 _opcode; // stores the last recieved opcode
|
||||
uint32 _remaining; // bytes amount of the next data packet
|
||||
|
||||
@ -215,13 +215,14 @@ bool ADTFile::LoadMem(ByteBuffer& buf)
|
||||
}
|
||||
else if(!strcmp((char*)fourcc,"MCNK"))
|
||||
{
|
||||
uint32 endpos = buf.rpos()+size;
|
||||
_chunks[mcnkid].hdr = buf.read<ADTMapChunkHeader>();
|
||||
uint8 _cc2[5];
|
||||
uint8 *mfcc = &_cc2[0];
|
||||
mfcc[4]=0;
|
||||
uint32 msize;
|
||||
bool mcal_compressed = false;
|
||||
while(buf.rpos()<buf.size())
|
||||
while(buf.rpos()<endpos)
|
||||
{
|
||||
buf.read(mfcc,4); flipcc(mfcc);
|
||||
buf.read((uint8*)&msize,4);
|
||||
@ -363,6 +364,7 @@ bool ADTFile::LoadMem(ByteBuffer& buf)
|
||||
|
||||
}
|
||||
mcnkid++;
|
||||
buf.rpos(endpos);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@ -30,7 +30,8 @@ AuthCrypt::~AuthCrypt()
|
||||
|
||||
}
|
||||
|
||||
void AuthCrypt::Init(BigNumber *K)
|
||||
// 3.3.5
|
||||
void AuthCrypt::Init_12340(BigNumber *K)
|
||||
{
|
||||
uint8 ClientDecryptionKey[SEED_KEY_SIZE] = { 0xCC, 0x98, 0xAE, 0x04, 0xE8, 0x97, 0xEA, 0xCA, 0x12, 0xDD, 0xC0, 0x93, 0x42, 0x91, 0x53, 0x57 };
|
||||
HmacHash serverEncryptHmac(SEED_KEY_SIZE, (uint8*)ClientDecryptionKey);
|
||||
@ -60,7 +61,7 @@ void AuthCrypt::Init(BigNumber *K)
|
||||
_initialized = true;
|
||||
}
|
||||
|
||||
void AuthCrypt::DecryptRecv(uint8 *data, size_t len)
|
||||
void AuthCrypt::DecryptRecv_12340(uint8 *data, size_t len)
|
||||
{
|
||||
if (!_initialized)
|
||||
return;
|
||||
@ -68,10 +69,84 @@ void AuthCrypt::DecryptRecv(uint8 *data, size_t len)
|
||||
_decrypt.UpdateData(len, data);
|
||||
}
|
||||
|
||||
void AuthCrypt::EncryptSend(uint8 *data, size_t len)
|
||||
void AuthCrypt::EncryptSend_12340(uint8 *data, size_t len)
|
||||
{
|
||||
if (!_initialized)
|
||||
return;
|
||||
|
||||
_encrypt.UpdateData(len, data);
|
||||
}
|
||||
|
||||
|
||||
void AuthCrypt::Init_8606(BigNumber *K)
|
||||
{
|
||||
uint8 *key = new uint8[SHA_DIGEST_LENGTH];
|
||||
|
||||
uint8 recvSeed[SEED_KEY_SIZE] = { 0x38, 0xA7, 0x83, 0x15, 0xF8, 0x92, 0x25, 0x30, 0x71, 0x98, 0x67, 0xB1, 0x8C, 0x4, 0xE2, 0xAA };
|
||||
HmacHash recvHash(SEED_KEY_SIZE, (uint8*)recvSeed);
|
||||
recvHash.UpdateBigNumber(K);
|
||||
recvHash.Finalize();
|
||||
memcpy(key, recvHash.GetDigest(), SHA_DIGEST_LENGTH);
|
||||
|
||||
_key.resize(SHA_DIGEST_LENGTH);
|
||||
std::copy(key, key + SHA_DIGEST_LENGTH, _key.begin());
|
||||
delete[] key;
|
||||
|
||||
_send_i = _send_j = _recv_i = _recv_j = 0;
|
||||
_initialized = true;
|
||||
}
|
||||
|
||||
|
||||
//1.12.2
|
||||
void AuthCrypt::Init_6005(BigNumber *K)
|
||||
{
|
||||
_send_i = _send_j = _recv_i = _recv_j = 0;
|
||||
|
||||
SetKey_6005(K->AsByteArray(),40);
|
||||
_initialized = true;
|
||||
|
||||
}
|
||||
|
||||
void AuthCrypt::DecryptRecv_6005(uint8 *data, size_t len)
|
||||
{
|
||||
if (!_initialized)
|
||||
return;
|
||||
|
||||
if (len < CRYPTED_RECV_LEN_6005)
|
||||
return;
|
||||
|
||||
for (size_t t = 0; t < CRYPTED_RECV_LEN_6005; t++)
|
||||
{
|
||||
_recv_i %= _key.size();
|
||||
uint8 x = (data[t] - _recv_j) ^ _key[_recv_i];
|
||||
++_recv_i;
|
||||
_recv_j = data[t];
|
||||
data[t] = x;
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void AuthCrypt::EncryptSend_6005(uint8 *data, size_t len)
|
||||
{
|
||||
if (!_initialized)
|
||||
return;
|
||||
if (len < CRYPTED_SEND_LEN_6005)
|
||||
return;
|
||||
|
||||
for (size_t t = 0; t < CRYPTED_SEND_LEN_6005; t++)
|
||||
{
|
||||
_send_i %= _key.size();
|
||||
uint8 x = (data[t] ^ _key[_send_i]) + _send_j;
|
||||
++_send_i;
|
||||
data[t] = _send_j = x;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void AuthCrypt::SetKey_6005(uint8 *key, size_t len)
|
||||
{
|
||||
_key.resize(len);
|
||||
std::copy(key, key + len, _key.begin());
|
||||
}
|
||||
|
||||
@ -30,15 +30,38 @@ class AuthCrypt
|
||||
AuthCrypt();
|
||||
~AuthCrypt();
|
||||
|
||||
void Init(BigNumber *K);
|
||||
void DecryptRecv(uint8 *, size_t);
|
||||
void EncryptSend(uint8 *, size_t);
|
||||
//Dummy
|
||||
void DecryptRecvDummy(uint8 *, size_t){return;};
|
||||
void EncryptSendDummy(uint8 *, size_t){return;};
|
||||
|
||||
//3.3.5
|
||||
void Init_12340(BigNumber *K);
|
||||
void DecryptRecv_12340(uint8 *, size_t);
|
||||
void EncryptSend_12340(uint8 *, size_t);
|
||||
|
||||
//2.4.3
|
||||
void Init_8606(BigNumber *K);
|
||||
|
||||
//1.12.X
|
||||
void Init_6005(BigNumber *K);
|
||||
void SetKey_6005(uint8 *, size_t);
|
||||
void DecryptRecv_6005(uint8 *, size_t);
|
||||
void EncryptSend_6005(uint8 *, size_t);
|
||||
|
||||
bool IsInitialized() { return _initialized; }
|
||||
|
||||
const static size_t CRYPTED_SEND_LEN_6005 = 6;
|
||||
const static size_t CRYPTED_RECV_LEN_6005 = 4;
|
||||
|
||||
|
||||
private:
|
||||
bool _initialized;
|
||||
//3.3.5
|
||||
SARC4 _decrypt;
|
||||
SARC4 _encrypt;
|
||||
bool _initialized;
|
||||
|
||||
//1.12.2
|
||||
std::vector<uint8> _key;
|
||||
uint8 _send_i, _send_j, _recv_i, _recv_j;
|
||||
};
|
||||
#endif
|
||||
|
||||
@ -272,6 +272,25 @@ class ByteBuffer
|
||||
if(buffer.size()) append(buffer.contents(),buffer.size());
|
||||
}
|
||||
|
||||
uint64 readPackGUID()
|
||||
{
|
||||
uint64 guid = 0;
|
||||
uint8 guidmark = 0;
|
||||
(*this) >> guidmark;
|
||||
|
||||
for(int i = 0; i < 8; ++i)
|
||||
{
|
||||
if(guidmark & (uint8(1) << i))
|
||||
{
|
||||
uint8 bit;
|
||||
(*this) >> bit;
|
||||
guid |= (uint64(bit) << (i * 8));
|
||||
}
|
||||
}
|
||||
|
||||
return guid;
|
||||
}
|
||||
|
||||
void appendPackGUID(uint64 guid)
|
||||
{
|
||||
if (_storage.size() < _wpos + sizeof(guid) + 1)
|
||||
|
||||
@ -18,6 +18,19 @@ void MPQHelper::Init()
|
||||
std::string ext = ".MPQ";
|
||||
std::string ldir = dir + GetLocale() + "/";
|
||||
|
||||
//1.12.X files
|
||||
_patches.push_front(dir+"base"+ext);
|
||||
_patches.push_front(dir+"dbc"+ext);
|
||||
_patches.push_front(dir+"fonts"+ext);
|
||||
_patches.push_front(dir+"interface"+ext);
|
||||
_patches.push_front(dir+"misc"+ext);
|
||||
_patches.push_front(dir+"model"+ext);
|
||||
_patches.push_front(dir+"sound"+ext);
|
||||
_patches.push_front(dir+"speech"+ext);
|
||||
_patches.push_front(dir+"terrain"+ext);
|
||||
_patches.push_front(dir+"texture"+ext);
|
||||
_patches.push_front(dir+"wmo"+ext);
|
||||
|
||||
// order goes from last opened to first opened file
|
||||
// ok maybe this is a bit too much but should work fine :)
|
||||
_patches.push_front(dir+"common"+ext);
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
#include "common.h"
|
||||
#include "MapTile.h"
|
||||
#include "log.h"
|
||||
#include "MemoryDataHolder.h"
|
||||
|
||||
MapTile::MapTile()
|
||||
{
|
||||
@ -12,13 +13,6 @@ MapTile::~MapTile()
|
||||
|
||||
void MapTile::ImportFromADT(ADTFile *adt)
|
||||
{
|
||||
// strip the path name from the dependency files, just store the plain filename
|
||||
for(std::vector<std::string>::iterator it = adt->_textures.begin(); it != adt->_textures.end(); it++)
|
||||
this->_textures.push_back(_PathToFileName(*it));
|
||||
for(std::vector<std::string>::iterator it = adt->_models.begin(); it != adt->_models.end(); it++)
|
||||
this->_models.push_back(_PathToFileName(*it));
|
||||
for(std::vector<std::string>::iterator it = adt->_wmos.begin(); it != adt->_wmos.end(); it++)
|
||||
this->_wmos.push_back(_PathToFileName(*it));
|
||||
|
||||
// import the height map
|
||||
for(uint32 ch=0; ch<CHUNKS_PER_TILE; ch++)
|
||||
@ -53,7 +47,9 @@ void MapTile::ImportFromADT(ADTFile *adt)
|
||||
for(uint32 ly = 0; ly < adt->_chunks[ch].hdr.nLayers; ly++)
|
||||
{
|
||||
uint32 texoffs = adt->_chunks[ch].layer[ly].textureId;
|
||||
_chunks[ch].texlayer.push_back(std::string("data/texture/") + NormalizeFilename(std::string(adt->_textures[texoffs])).c_str());
|
||||
char fname[255];
|
||||
MemoryDataHolder::MakeTextureFilename(fname,adt->_textures[texoffs]);
|
||||
_chunks[ch].texlayer.push_back(fname);
|
||||
}
|
||||
|
||||
memcpy(_chunks[ch].alphamap, adt->_chunks[ch].alphamap, adt->_chunks[ch].hdr.sizeAlpha - 8);
|
||||
@ -90,7 +86,9 @@ void MapTile::ImportFromADT(ADTFile *adt)
|
||||
d.flags = mddf.flags;
|
||||
d.uniqueid = mddf.uniqueid;
|
||||
d.MPQpath = adt->_models[mddf.id];
|
||||
d.model = std::string("./data/model/") + NormalizeFilename(_PathToFileName(adt->_models[mddf.id]));
|
||||
char fname[255];
|
||||
MemoryDataHolder::MakeModelFilename(fname,adt->_models[mddf.id]);
|
||||
d.model = fname;
|
||||
// this .mdx -> .m2 transformation is annoying >.< - replace "mdx" and end of string with "m2"
|
||||
// d.model = d.model.substr(0, d.model.length() - 3) + "m2";
|
||||
// 3.1.3 - no more .mdx in ADT
|
||||
@ -115,7 +113,9 @@ void MapTile::ImportFromADT(ADTFile *adt)
|
||||
wmo.flags = modf.flags;
|
||||
wmo.uniqueid = modf.uniqueid;
|
||||
wmo.MPQpath = adt->_wmos[modf.id];
|
||||
wmo.model = std::string("./data/wmo/") + NormalizeFilename(_PathToFileName(adt->_wmos[modf.id]));
|
||||
char fname[255];
|
||||
MemoryDataHolder::MakeWMOFilename(fname,adt->_wmos[modf.id]);
|
||||
wmo.model = fname;
|
||||
_wmo_data.push_back(wmo);
|
||||
}
|
||||
|
||||
|
||||
@ -1146,7 +1146,7 @@ void FetchTexturesFromModel(ByteBuffer bb)
|
||||
|
||||
bb.read((uint8*)&header, sizeof(header));
|
||||
|
||||
if (header.version[0] != 8 || header.version[1] != 1 || header.version[2] != 0 || header.version[3] != 0) {
|
||||
if (header.version != 0x108) {
|
||||
printf("Not M2 model file!");
|
||||
return;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user