// Add world simulation bool Physics::addSimulation(vec pos) { if (!enabled) { return true; } uint8_t block; uint8_t meta; map->getBlock(pos, &block, &meta); SimBlock simulationBlock(block, pos, meta); // Dont add duplicates for (std::vector<Sim>::iterator simIt = simList.begin(); simIt != simList.end(); simIt++) { vec itpos = simIt->blocks[0].pos; if (itpos.x() == pos.x() && itpos.y() == pos.y() && itpos.z() == pos.z()) { return true; } } // Simulating water if (isWaterBlock(block)) { simList.push_back(Sim(TYPE_WATER, simulationBlock)); return true; } // Simulating lava else if (isLavaBlock(block)) { simList.push_back(Sim(TYPE_LAVA, simulationBlock)); return true; } return false; }
// Add world simulation bool Physics::addSimulation(vec pos) { if(!enabled) return true; uint8 block; uint8 meta; Map::get()->getBlock(pos, &block, &meta); SimBlock simulationBlock(block, pos, meta); // Simulating water if(isWaterBlock(block)) { simList.push_back(Sim(TYPE_WATER, simulationBlock)); return true; } // Simulating lava else if(isLavaBlock(block)) { simList.push_back(Sim(TYPE_LAVA, simulationBlock)); return true; } return false; }
// Physics loop bool Physics::update() { updateFall(); updateMinecart(); if (!enabled) { return true; } // Check if needs to be updated if (simList.empty()) { return true; } std::vector<vec> toAdd; std::vector<vec> toRem; std::set<vec> changed; clock_t starttime = clock(); LOG(INFO, "Physics", "Simulating " + dtos(simList.size()) + " items!"); uint32_t listSize = simList.size(); for (uint32_t simIt = 0; simIt < listSize; simIt++) { vec pos = simList[simIt].blocks[0].pos; // Blocks uint8_t block, meta; ServerInstance->map(map)->getBlock(pos, &block, &meta); simList[simIt].blocks[0].id = block; simList[simIt].blocks[0].meta = meta; bool used = false; for (int i = 0; i < 5; i++) { vec local(pos); bool falling = false; switch (i) { case 0: local += vec(0, -1, 0); // First tries to go down falling = true; break; case 1: local += vec(1, 0, 0); // Might be bad to have the 4 cardinal dir' // so predictable break; case 2: local += vec(-1, 0, 0); break; case 3: local += vec(0, 0, 1); break; case 4: local += vec(0, 0, -1); break; case 5: // local += vec(0,1,0); // Going UP break; } uint8_t newblock, newmeta; ServerInstance->map(map)->getBlock(pos, &block, &meta); ServerInstance->map(map)->getBlock(local, &newblock, &newmeta); if (!isLiquidBlock(block)) { toRem.push_back(pos); break; } if ((isWaterBlock(newblock) && isWaterBlock(block)) || (isLavaBlock(newblock) && isLavaBlock(block)) || (isLiquidBlock(block) && mayFallThrough(newblock))) { if (falling && !isLiquidBlock(newblock)) { ServerInstance->map(map)->setBlock(local, block, meta); changed.insert(local); ServerInstance->map(map)->setBlock(pos, BLOCK_AIR, 0); changed.insert(pos); toRem.push_back(pos); toAdd.push_back(local); used = true; continue; } if (falling && isLiquidBlock(newblock)) { int top = 8 - meta; int bot = 8 - newmeta; int volume = top + bot; if (volume > 8) { top = volume - 8; bot = 8; } else { top = 0; bot = volume; } int a_meta = 8 - top; int a_newmeta = 8 - bot; toAdd.push_back(local); if (a_meta == meta && a_newmeta == newmeta) { toRem.push_back(pos); toRem.push_back(local); continue; } if ((isWaterBlock(block) && a_meta < 8) || (isLavaBlock(block) && a_meta < 4)) { ServerInstance->map(map)->setBlock(pos, block, a_meta); changed.insert(pos); } else { ServerInstance->map(map)->setBlock(pos, BLOCK_AIR, 0); changed.insert(pos); } ServerInstance->map(map)->setBlock(local, block, a_newmeta); used = true; toAdd.push_back(local); toAdd.push_back(pos); changed.insert(pos); continue; } if (!isLiquidBlock(newblock)) { if (!falling) { if ((isWaterBlock(block) && meta == 7) || (isLavaBlock(block) && meta >= 3)) { toRem.push_back(pos); break; } } // We are spreading onto dry area. newmeta = 7; ServerInstance->map(map)->setBlock(local, block, newmeta); changed.insert(local); meta++; if (meta < 8) { ServerInstance->map(map)->setBlock(pos, block, meta); changed.insert(pos); } else { ServerInstance->map(map)->setBlock(pos, BLOCK_AIR, 0); changed.insert(pos); toRem.push_back(pos); } toAdd.push_back(local); used = true; continue; } if (meta < newmeta - 1 || (meta == newmeta && falling)) { newmeta --; ServerInstance->map(map)->setBlock(local, block, newmeta); changed.insert(local); meta ++; if (meta < 8) { ServerInstance->map(map)->setBlock(pos, block, meta); changed.insert(pos); } else { ServerInstance->map(map)->setBlock(pos, BLOCK_AIR, 0); changed.insert(pos); toRem.push_back(pos); } toAdd.push_back(local); used = true; continue; } } } if (!used) { toRem.push_back(pos); } } for (int i = int(toRem.size()) - 1; i >= 0; i--) { removeSimulation(toRem[i]); } for (size_t i = 0; i < toAdd.size(); i++) { addSimulation(toAdd[i]); } ServerInstance->map(map)->sendMultiBlocks(changed); clock_t endtime = clock() - starttime; // LOG(INFO, "Physics", "Exit simulation, took " + dtos(endtime * 1000 / CLOCKS_PER_SEC) + " ms, " + dtos(simList.size()) + " items left"); return true; }
// Physics loop bool Physics::update() { if (!enabled) { return true; } // Check if needs to be updated if (simList.empty()) { return true; } std::set<vec> changed; //if(this->lasttime == NULL) this->lasttime = 0; clock_t diffTime = clock() - lasttime; LOG(INFO, "Physics", "Simulating " + dtos(simList.size()) + " items!"); uint32_t listSize = simList.size(); for (uint32_t simIt = 0; simIt < listSize; simIt++) { //Get Pos vec pos = simList[simIt].blocks[0].pos; //Render the block? bool render = simList[simIt].blocks[0].render; //Meta -> High of water(0-7), State of redstone (15-0) uint8_t block, meta; Mineserver::get()->map(map)->getBlock(pos, &block, &meta); if(isWaterBlock(block) || (isLavaBlock(block) && diffTime > 4000)) { updateFluid(simIt); changed.insert(pos); } else if(isRedstone(block)) { updateRedstone(simIt); changed.insert(pos); } else { removeSimulation(pos); uint8_t around[6][2]; vec vectors[6]; getBlocksAround(pos, vectors, around); for(int i = 0; i < 5; i ++) { addSimulation(vectors[i]); } break; } } Mineserver::get()->map(map)->sendMultiBlocks(changed); lasttime = clock(); //clock_t endtime = clock() - starttime; // LOG(INFO, "Physics", "Exit simulation, took " + dtos(endtime * 1000 / CLOCKS_PER_SEC) + " ms, " + dtos(simList.size()) + " items left"); return true; }