Sound::Sound(const std::wstring& waveResourceName, bool loopForever, bool hasReverb) : m_SoundCallbacks(this), m_SubmixVoice(nullptr) { auto waveFile = RiffFile::Create(waveResourceName); Assert(waveFile.GetFormat() == RiffFourCC::WAVE); ZeroMemory(&m_WaveFormat, sizeof(m_WaveFormat)); ZeroMemory(&m_AudioBuffer, sizeof(m_AudioBuffer)); const auto& formatChunk = waveFile.GetChunk(RiffFourCC::FMT); Assert(sizeof(m_WaveFormat) >= formatChunk.GetSize()); memcpy(&m_WaveFormat, formatChunk.GetData(), formatChunk.GetSize()); auto& dataChunk = waveFile.GetChunk(RiffFourCC::DATA); m_SoundDataBuffer = std::move(dataChunk.GetDataBuffer()); m_AudioBuffer.AudioBytes = dataChunk.GetSize(); m_AudioBuffer.pAudioData = m_SoundDataBuffer.get(); m_AudioBuffer.Flags = XAUDIO2_END_OF_STREAM; m_AudioBuffer.LoopCount = loopForever ? XAUDIO2_LOOP_INFINITE : 0; if (hasReverb) { m_SubmixVoice = AudioManager::GetInstance().CreateSubmixVoice(m_WaveFormat); } }
void GLMapRenderer::DrawColumnDLight(int cx, int cy, int cz, spades::Vector3 eye, const std::vector<GLDynamicLight>& lights){ cx &= numChunkWidth -1; cy &= numChunkHeight - 1; for(int z = std::max(cz, 0); z < numChunkDepth; z++) GetChunk(cx, cy, z)->RenderDLightPass(lights); for(int z = std::min(cz - 1, 63); z >= 0; z--) GetChunk(cx, cy, z)->RenderDLightPass(lights); }
void GLMapRenderer::DrawColumnSunlight(int cx, int cy, int cz, spades::Vector3 eye){ cx &= numChunkWidth -1; cy &= numChunkHeight - 1; for(int z = std::max(cz, 0); z < numChunkDepth; z++) GetChunk(cx, cy, z)->RenderSunlightPass(); for(int z = std::min(cz - 1, 63); z >= 0; z--) GetChunk(cx, cy, z)->RenderSunlightPass(); }
// return false if _takeIdx not found (e.g. empty *item*) bool SNM_TakeParserPatcher::GetTakeChunkPos(int _takeIdx, int* _pos, int* _len) { int tkCount = 0; const char* p = strstr(GetChunk()->Get(), "\nTAKE"); // force GetChunk() (+ add fake 1st take if needed) while (p) { if (IsValidTakeChunkLine(p)) { if (tkCount == _takeIdx) { // is there a next take ? const char* p2 = strstr(p+1, "\nTAKE"); while (p2) { if (IsValidTakeChunkLine(p2)) break; p2 = strstr(p2+1, "\nTAKE"); } *_pos = (int)(p+1 - m_chunk->Get()); if (_len) { if (p2 && !strncmp(p2, "\nTAKE", 5)) *_len = (int)(p2-p); // it's the last take else *_len = strlen(p+1)-2; // -2 for final ">\n" } return true; } tkCount++; } p = strstr(p+1, "\nTAKE"); } return false; }
void OnSetChunkNeighborhood(Packet& packet) { u16 chunkID, neighborhoodID; packet.Read(chunkID); packet.Read(neighborhoodID); auto chmgr = ChunkManager::Get(); auto ch = chmgr->GetChunk(chunkID); if(!ch) { logger << "Server tried to set neighborhood of unknown chunk!"; return; } auto neigh = chmgr->GetNeighborhood(neighborhoodID); if(!neigh) { neigh = chmgr->CreateNeighborhood(); neigh->neighborhoodID = neighborhoodID; neigh->chunkSize = ivec3{ch->width, ch->height, ch->depth}; } ch->SetNeighborhood(neigh); packet.Read<ivec3>(ch->positionInNeighborhood); logger << ch->positionInNeighborhood; neigh->UpdateChunkTransform(ch); }
void OnSetBlock(Packet& packet) { auto chmgr = ChunkManager::Get(); u8 orientation; u16 chunkID, blockType; ivec3 vxPos; // Assume vxPos is in bounds packet.Read(chunkID); packet.Read<ivec3>(vxPos); packet.Read(blockType); orientation = blockType & 3; blockType >>= 2; auto ch = chmgr->GetChunk(chunkID); if(!ch) { logger << "Missing chunkID " << chunkID; return; } if(blockType) { auto blk = ch->CreateBlock(vxPos, blockType); if(blk) blk->orientation = orientation; else logger << "Block create failed at " << vxPos; }else{ ch->DestroyBlock(vxPos); } }
static int DoNextChunk( T3dsLoaderPers *pers, int endofs ){ T3dsChunk *chunk; #ifdef DEBUG_PM_3DS printf( "DoNextChunk: endofs %d\n",endofs ); #endif while ( pers->cofs < endofs ) { long nextofs = pers->cofs; if ( ( chunk = GetChunk( pers ) ) == NULL ) { return 0; } if ( !chunk->len ) { return 0; } nextofs += chunk->len; #ifdef DEBUG_PM_3DS_EX printf( "Chunk %04x (%s), len %d pers->cofs %x\n",chunk->id,DebugGetChunkName( chunk->id ),chunk->len,pers->cofs ); #endif /*** version ***/ if ( chunk->id == CHUNK_VERSION ) { /* at this point i get the 3ds file version. since there */ /* might be new additions to the 3ds file format in 4.0 */ /* it might be a good idea to store the version somewhere */ /* for later handling or message displaying */ /* get the version */ int version; version = GetWord( pers ); GetWord( pers ); #ifdef DEBUG_PM_3DS printf( "FileVersion: %d\n",version ); #endif /* throw out a warning for version 4 models */ if ( version == 4 ) { _pico_printf( PICO_WARNING, "3DS version is 4. Model might load incorrectly." ); } /* store the 3ds file version in pico special field 0 */ /* PicoSetSurfaceSpecial(pers->surface,0,version); */ /* ydnar: this was causing a crash accessing uninitialized surface */ /* rest of chunk is skipped here */ } /*** editor data ***/ if ( chunk->id == CHUNK_EDITOR_DATA ) { if ( !DoNextEditorDataChunk( pers,nextofs ) ) { return 0; } continue; } /* skip unknown chunk */ pers->cofs = nextofs; if ( pers->cofs >= pers->maxofs ) { break; } } return 1; }
void GLRadiosityRenderer::UpdateChunk(int cx, int cy, int cz) { Chunk &c = GetChunk(cx, cy, cz); if (!c.dirty) return; int originX = cx * ChunkSize; int originY = cy * ChunkSize; int originZ = cz * ChunkSize; for (int z = c.dirtyMinZ; z <= c.dirtyMaxZ; z++) for (int y = c.dirtyMinY; y <= c.dirtyMaxY; y++) for (int x = c.dirtyMinX; x <= c.dirtyMaxX; x++) { IntVector3 pos; pos.x = (x + originX); pos.y = (y + originY); pos.z = (z + originZ); Result res = Evaluate(pos); c.dataFlat[z][y][x] = EncodeValue(res.base); c.dataX[z][y][x] = EncodeValue(res.x); c.dataY[z][y][x] = EncodeValue(res.y); c.dataZ[z][y][x] = EncodeValue(res.z); } c.dirty = false; c.transferDone = false; }
// assumes _chunk always begins with "TAKE" // _pos: start pos of the take if known, for optimization (-1 if unknown) // returns the end position after insertion (or -1 if failed) int SNM_TakeParserPatcher::InsertTake(int _takeIdx, WDL_FastString* _chunk, int _pos) { int afterPos = -1; int length = _chunk ? _chunk->GetLength() : 0; if (length && GetChunk()) // force GetChunk() (force cache + add fake 1st take if needed) { // last pos? if (_takeIdx >= CountTakesInChunk()) { afterPos = AddLastTake(_chunk); } // other pos else { int pos = _pos; if (pos < 0) GetTakeChunkPos(_takeIdx, &pos); if (pos >= 0) { m_chunk->Insert(_chunk->Get(), pos); afterPos = pos + length; m_currentTakeCount++; // *always* reflect the nb of takes in the *chunk* m_updates++; // as we're directly working on the cached chunk.. } } } return afterPos; }
const unsigned char C_Game::GetCubeType(const int h, const int i, const int j) { int diffX = 0; int diffY = 0; if(h < 0) diffX = 1; if(i < 0) diffY = 1; int a = (h+diffX)/CHUNK_SIZE; if(h < 0) a--; int b = (i+diffY)/CHUNK_SIZE; if(i < 0) b--; MinecraftChunk *ch = GetChunk(a, b); int xx = h + diffX - (int)((h+diffX)/CHUNK_SIZE) * CHUNK_SIZE; if(h < 0) { if(xx <= 0) xx = CHUNK_SIZE - 1 + xx; } int yy = i + diffY - (int)((i+diffY)/CHUNK_SIZE) * CHUNK_SIZE; if(i < 0) { if(yy <= 0) yy = CHUNK_SIZE - 1 + yy; } return ch->_chunkMap[xx][yy][j]; }
void C_Game::CreateRandomChunk(const int a, const int b) { if(GetChunk(a, b) != NULL) return; MinecraftChunk *temp = new MinecraftChunk; temp->x = a; temp->y = b; temp->_hidden = true; _chunks.push_back(temp); for(int h=0;h<CHUNK_SIZE;h++) { for(int i=0;i<CHUNK_SIZE;i++) { for(int j=0;j<CHUNK_ZVALUE;j++) { _chunks.back()->_chunkMap[h][i][j] = (rand() % (NB_TYPE_CUBE-1)) +1; } } } for(int h=0;h<CHUNK_SIZE;h++) for(int i=0;i<CHUNK_SIZE;i++) for(int j=CHUNK_ZVALUE/2;j<CHUNK_ZVALUE;j++) _chunks.back()->_chunkMap[h][i][j] = CUBE_AIR; }
void HierarchicalPathfinder::FindNearestNavcellInRegions(const std::set<RegionID>& regions, u16& iGoal, u16& jGoal, pass_class_t passClass) { // Find the navcell in the given regions that's nearest to the goal navcell: // * For each region, record the (squared) minimal distance to the goal point // * Sort regions by that underestimated distance // * For each region, find the actual nearest navcell // * Stop when the underestimated distances are worse than the best real distance std::vector<std::pair<u32, RegionID> > regionDistEsts; // pair of (distance^2, region) for (const RegionID& region : regions) { int i0 = region.ci * CHUNK_SIZE; int j0 = region.cj * CHUNK_SIZE; int i1 = i0 + CHUNK_SIZE - 1; int j1 = j0 + CHUNK_SIZE - 1; // Pick the point in the chunk nearest the goal int iNear = Clamp((int)iGoal, i0, i1); int jNear = Clamp((int)jGoal, j0, j1); int dist2 = (iNear - iGoal)*(iNear - iGoal) + (jNear - jGoal)*(jNear - jGoal); regionDistEsts.emplace_back(dist2, region); } // Sort by increasing distance (tie-break on RegionID) std::sort(regionDistEsts.begin(), regionDistEsts.end()); int iBest = iGoal; int jBest = jGoal; u32 dist2Best = std::numeric_limits<u32>::max(); for (auto& pair : regionDistEsts) { if (pair.first >= dist2Best) break; RegionID region = pair.second; int i, j; u32 dist2; GetChunk(region.ci, region.cj, passClass).RegionNavcellNearest(region.r, iGoal, jGoal, i, j, dist2); if (dist2 < dist2Best) { iBest = i; jBest = j; dist2Best = dist2; } } iGoal = iBest; jGoal = jBest; }
// assumes _newTakeChunk always begins with "TAKE" bool SNM_TakeParserPatcher::ReplaceTake(int _startTakePos, int _takeLength, WDL_FastString* _newTakeChunk) { bool updated = false; if (GetChunk() && _newTakeChunk && _startTakePos >= 0) // force GetChunk() (force cache + add fake 1st take if needed) { int prevLgth = GetChunk()->GetLength(); GetChunk()->DeleteSub(_startTakePos, _takeLength); m_updates++; // as we're directly working on the cached chunk.. updated = true; m_currentTakeCount--; if (prevLgth > GetChunk()->GetLength()) // see WDL_FastString.DeleteSub() { GetChunk()->Insert(_newTakeChunk->Get(), _startTakePos, _newTakeChunk->GetLength()); m_updates++; m_currentTakeCount++; } } return updated; }
WavAudioStream::WavAudioStream(IStream *s, bool ac) { SPADES_MARK_FUNCTION(); stream = s; autoClose = ac; // skip header s->SetPosition(12 + s->GetPosition()); while(s->GetPosition() < s->GetLength()) { RiffChunkInfo info = ReadChunkInfo(); chunks[info.name] = info; s->SetPosition(info.dataPosition + info.length); } const RiffChunkInfo& fmt = GetChunk("fmt "); stream->SetPosition(fmt.dataPosition); stream->ReadLittleShort();// ?? channels = stream->ReadLittleShort(); rate = stream->ReadLittleInt(); stream->ReadLittleInt(); stream->ReadLittleShort(); int bits = stream->ReadLittleShort(); switch(bits){ case 8: sampleFormat = UnsignedByte; break; case 16: sampleFormat = SignedShort; break; case 32: sampleFormat = SingleFloat; break; default: SPRaise("Unsupported bit count: %d", bits); } dataChunk = &GetChunk("data"); stream->SetPosition(dataChunk->dataPosition); startPos = dataChunk->dataPosition; endPos = dataChunk->dataPosition + dataChunk->length; }
bool BabelGlue::GetPos(GPXCoord *pos) { const char *file; unsigned long fs; int num; long crc; kGUIString created; kGUIString coords; kGUIStringSplit ss; bool gotnew=false; crc=kGUI::FileCRC("gpsbabel.kml"); file=(const char *)kGUI::LoadFile("gpsbabel.kml",&fs); if(file) { /* get created string */ if(GetChunk("<Snippet>",file,&created)) { /* get coords */ if(GetChunk("<coordinates>",file,&coords)) { /* created only has 1 second resolution so we use crc too */ if(strcmp(created.GetString(),m_created.GetString()) || m_crc!=crc) { num=ss.Split(&coords,","); if((num==2) || (num==3)) { /* lon/lat/alt */ m_created.SetString(&created); m_crc=crc; m_lat=ss.GetWord(1)->GetDouble(); m_lon=ss.GetWord(0)->GetDouble(); pos->Set(m_lat,m_lon); gotnew=true; } } } } delete []file; } return(gotnew); }
bool World::UnloadChunk(Chunk::ChunkPosition chunkPosition) { Chunk* pChunk = GetChunk(chunkPosition.x, chunkPosition.y, chunkPosition.z); if(pChunk == nullptr) return false; m_vpChunks.erase(std::remove(m_vpChunks.begin(), m_vpChunks.end(), pChunk), m_vpChunks.end()); m_vpChunksToGenerate.erase(std::remove(m_vpChunksToGenerate.begin(), m_vpChunksToGenerate.end(), pChunk), m_vpChunksToGenerate.end()); m_vpChunksToMesh.erase(std::remove(m_vpChunksToMesh.begin(), m_vpChunksToMesh.end(), pChunk), m_vpChunksToMesh.end()); m_vpChunksToRender.erase(std::remove(m_vpChunksToRender.begin(), m_vpChunksToRender.end(), pChunk), m_vpChunksToRender.end()); delete pChunk; pChunk = nullptr; return true; }
BOOL CADORecordset::GetChunk(int nIndex, CString& strValue) { _variant_t vtIndex; vtIndex.vt = VT_I2; vtIndex.iVal = nIndex; FieldPtr pField = m_pRecordset->Fields->GetItem(vtIndex); return GetChunk(pField, strValue); }
BOOL CADORecordset::GetChunk(int nIndex, LPVOID lpData) { _variant_t vtIndex; vtIndex.vt = VT_I2; vtIndex.iVal = nIndex; FieldPtr pField = m_pRecordset->Fields->GetItem(vtIndex); return GetChunk(pField, lpData); }
void nuiAiffReader::SetPosition(uint32 position) { if (!mInitialized) return; Chunk* pDataChunk = GetChunk("SSND"); NGL_ASSERT(pDataChunk); nglFileOffset StreamPosition = pDataChunk->mDataPosition + mInfo.GetChannels() * (mInfo.GetBitsPerSample() / 8) * position; mrStream.SetPos(StreamPosition); mPosition = position; }
// assumes that _tkChunk begins with "TAKE" // returns the end position after insertion (or -1 if failed) int SNM_TakeParserPatcher::AddLastTake(WDL_FastString* _tkChunk) { int afterPos = -1; if (_tkChunk && _tkChunk->GetLength() && GetChunk()) // force GetChunk() (cache + add fake 1st take if needed) { m_chunk->Insert(_tkChunk->Get(), m_chunk->GetLength()-2, _tkChunk->GetLength()); //-2: before ">\n" afterPos = m_chunk->GetLength()-2; m_currentTakeCount++; // *always* reflect the nb of takes in the *chunk* m_updates++; // as we're directly working on the cached chunk.. } return afterPos; }
void nuiWaveReader::SetPosition(int64 position) { if (!mInitialized) return; Chunk* pDataChunk = GetChunk("data"); nglFileOffset newStreamPosition = pDataChunk->mDataPosition + mInfo.GetChannels() * (mInfo.GetBitsPerSample() / 8) * position; nglFileOffset newPos = mrStream.SetPos(newStreamPosition); NGL_ASSERT(newPos == newStreamPosition); mPosition = position; }
Chunk* World::GetChunkWorldCoords(int x, int y, int z) { int voxelX = x%Chunk::CHUNKSIZEX; int voxelY = y%Chunk::CHUNKSIZEY; int voxelZ = z%Chunk::CHUNKSIZEZ; if(voxelX < 0) voxelX += Chunk::CHUNKSIZEX; if(voxelY < 0) voxelY += Chunk::CHUNKSIZEY; if(voxelZ < 0) voxelZ += Chunk::CHUNKSIZEZ; int chunkX = (x-voxelX)/Chunk::CHUNKSIZEX; int chunkY = (y-voxelY)/Chunk::CHUNKSIZEY; int chunkZ = (z-voxelZ)/Chunk::CHUNKSIZEZ; Chunk* pChunk = GetChunk(chunkX, chunkY, chunkZ); return pChunk; }
bool ChunkedFile::prepareLoadedData() { FileChunk* chunk = GetChunk("MVER"); if (!chunk) return false; // Check version file_MVER* version = chunk->As<file_MVER>(); if (version->fcc != MverMagic.fcc) return false; if (version->ver != FILE_FORMAT_VERSION) return false; return true; }
int SoundManager::PlayLoopingSample(std::string _filename) { //Look the sound up, it's probably already loaded. If not then load it. if(status_ != SoundStatus::OK) return -1; Mix_Chunk* sample = GetChunk(_filename); if(sample) { //Play the sound return Mix_PlayChannel(-1, sample, -1); } return -1; }
Chunk* ChunkManager::GetChunkFromPosition(float posX, float posY, float posZ) { int gridX = (int)((posX + Chunk::BLOCK_RENDER_SIZE) / Chunk::CHUNK_SIZE); int gridY = (int)((posY + Chunk::BLOCK_RENDER_SIZE) / Chunk::CHUNK_SIZE); int gridZ = (int)((posZ + Chunk::BLOCK_RENDER_SIZE) / Chunk::CHUNK_SIZE); if (posX <= -0.5f) gridX -= 1; if (posY <= -0.5f) gridY -= 1; if (posZ <= -0.5f) gridZ -= 1; return GetChunk(gridX, gridY, gridZ); }
// different from the API's CountTakes(MediaItem*), this method deals with the chunk int SNM_TakeParserPatcher::CountTakesInChunk() { if (m_currentTakeCount < 0) { m_currentTakeCount = 0; const char* p = strstr(GetChunk()->Get(), "\nTAKE"); // force GetChunk() (force cache + add fake 1st take if needed) while (p) { if (IsValidTakeChunkLine(p)) m_currentTakeCount++; p = strstr((char*)(p+1), "\nTAKE"); } } return m_currentTakeCount; }
Voxel* World::GetVoxel(int x, int y, int z) { int voxelX = x%Chunk::CHUNKSIZEX; int voxelY = y%Chunk::CHUNKSIZEY; int voxelZ = z%Chunk::CHUNKSIZEZ; if(voxelX < 0) voxelX += Chunk::CHUNKSIZEX; if(voxelY < 0) voxelY += Chunk::CHUNKSIZEY; if(voxelZ < 0) voxelZ += Chunk::CHUNKSIZEZ; int chunkX = (x-voxelX)/Chunk::CHUNKSIZEX; int chunkY = (y-voxelY)/Chunk::CHUNKSIZEY; int chunkZ = (z-voxelZ)/Chunk::CHUNKSIZEZ; Chunk* pChunk = GetChunk(chunkX, chunkY, chunkZ); if(pChunk != nullptr) { return pChunk->GetVoxel(voxelX, voxelY, voxelZ); } return nullptr; }
int SoundManager::PlayEnqueuedSample(std::string _filename, unsigned char _distance) { //Look the sound up, it's probably already loaded. If not then load it. if(status_ != SoundStatus::OK) return -1; Mix_Chunk* sample = GetChunk(_filename); if(sample) { //Play the sound int channel = Mix_PlayChannel(-1, sample, 0); if(channel >= 0) Mix_SetDistance(channel, _distance); return channel; } return -1; }
void C_Game::CheckChunksCubesVisibility(const int x, const int y) { MinecraftChunk *ch = GetChunk(x, y); if(ch == NULL) return; if(!ch->_hidden) return; unsigned char tab[CHUNK_SIZE+2][CHUNK_SIZE+2][CHUNK_ZVALUE+2]; for(int h=0;h<CHUNK_SIZE+2;h++) for(int i=0;i<CHUNK_SIZE+2;i++) for(int j=0;j<CHUNK_ZVALUE+2;j++) tab[h][i][j] = CUBE_DIRT; for(int h=0;h<CHUNK_SIZE;h++) for(int i=0;i<CHUNK_SIZE;i++) for(int j=0;j<CHUNK_ZVALUE;j++) tab[1+h][1+i][1+j] = ch->_chunkMap[h][i][j]; for(int h=1;h<CHUNK_SIZE+1;h++) { for(int i=1;i<CHUNK_SIZE+1;i++) { for(int j=1;j<CHUNK_ZVALUE+1;j++) { if(tab[h][i][j] != CUBE_AIR) { if( (h-1 >= 0 && tab[h-1][i][j] == CUBE_AIR) || ( h+1 < CHUNK_SIZE && tab[h+1][i][j] == CUBE_AIR) || ( i-1 >= 0 && tab[h][i-1][j] == CUBE_AIR) || ( i+1 < CHUNK_SIZE && tab[h][i+1][j] == CUBE_AIR) || ( j-1 >= 0 && tab[h][i][j-1] == CUBE_AIR) || ( j+1 < CHUNK_ZVALUE && tab[h][i][j+1] == CUBE_AIR) ) { tabCube temp; temp.x = h-1 + x*CHUNK_SIZE; temp.y = i-1 + y * CHUNK_SIZE; temp.z = j-1; _tabCube[tab[h][i][j]].push_back(temp); } } } } } ch->_hidden = false; }
void C_Game::DeleteChunkFromMemory(const int x, const int y) { MinecraftChunk *ch = GetChunk(x, y); if(ch == NULL) return; unsigned char tab[CHUNK_SIZE+2][CHUNK_SIZE+2][CHUNK_ZVALUE+2]; for(int h=0;h<CHUNK_SIZE+2;h++) for(int i=0;i<CHUNK_SIZE+2;i++) for(int j=0;j<CHUNK_ZVALUE+2;j++) tab[h][i][j] = CUBE_DIRT; for(int h=0;h<CHUNK_SIZE;h++) for(int i=0;i<CHUNK_SIZE;i++) for(int j=0;j<CHUNK_ZVALUE;j++) tab[1+h][1+i][1+j] = ch->_chunkMap[h][i][j]; for(int h=1;h<CHUNK_SIZE+1;h++) { for(int i=1;i<CHUNK_SIZE+1;i++) { for(int j=1;j<CHUNK_ZVALUE+1;j++) { if(tab[h][i][j] != CUBE_AIR) { if( (h-1 >= 0 && tab[h-1][i][j] == CUBE_AIR) || ( h+1 < CHUNK_SIZE && tab[h+1][i][j] == CUBE_AIR) || ( i-1 >= 0 && tab[h][i-1][j] == CUBE_AIR) || ( i+1 < CHUNK_SIZE && tab[h][i+1][j] == CUBE_AIR) || ( j-1 >= 0 && tab[h][i][j-1] == CUBE_AIR) || ( j+1 < CHUNK_ZVALUE && tab[h][i][j+1] == CUBE_AIR) ) { DeleteCubeOfVector(tab[h][i][j], (h-1 + x*CHUNK_SIZE), (i-1 + y * CHUNK_SIZE), j-1); } } } } } SaveChunk(x, y); for(unsigned int i=0;i<_chunks.size();i++) if(_chunks[i]->x == x && _chunks[i]->y == y) _chunks.erase(_chunks.begin()+i); delete ch; }