4jcraft/Minecraft.World/WorldGen/Structures/Villages.cpp
MatthewBeshay a0fdc643d1 Merge branch 'upstream-dev' into cleanup/nullptr-replacement
# Conflicts:
#	Minecraft.Client/Network/PlayerChunkMap.cpp
#	Minecraft.Client/Network/PlayerList.cpp
#	Minecraft.Client/Network/ServerChunkCache.cpp
#	Minecraft.Client/Platform/Common/Consoles_App.cpp
#	Minecraft.Client/Platform/Common/DLC/DLCManager.cpp
#	Minecraft.Client/Platform/Common/GameRules/LevelGenerationOptions.cpp
#	Minecraft.Client/Platform/Common/GameRules/LevelRuleset.cpp
#	Minecraft.Client/Platform/Common/Tutorial/Tutorial.cpp
#	Minecraft.Client/Platform/Common/Tutorial/TutorialTask.cpp
#	Minecraft.Client/Platform/Common/UI/IUIScene_CreativeMenu.cpp
#	Minecraft.Client/Platform/Common/UI/UIComponent_Panorama.cpp
#	Minecraft.Client/Platform/Common/UI/UIController.cpp
#	Minecraft.Client/Platform/Common/UI/UIController.h
#	Minecraft.Client/Platform/Extrax64Stubs.cpp
#	Minecraft.Client/Platform/Windows64/4JLibs/inc/4J_Input.h
#	Minecraft.Client/Platform/Windows64/4JLibs/inc/4J_Storage.h
#	Minecraft.Client/Player/EntityTracker.cpp
#	Minecraft.Client/Player/ServerPlayer.cpp
#	Minecraft.Client/Rendering/EntityRenderers/PlayerRenderer.cpp
#	Minecraft.Client/Textures/Packs/DLCTexturePack.cpp
#	Minecraft.Client/Textures/Stitching/StitchedTexture.cpp
#	Minecraft.Client/Textures/Stitching/TextureMap.cpp
#	Minecraft.Client/Textures/Textures.cpp
#	Minecraft.World/Blocks/NotGateTile.cpp
#	Minecraft.World/Blocks/PressurePlateTile.cpp
#	Minecraft.World/Blocks/TileEntities/PotionBrewing.cpp
#	Minecraft.World/Enchantments/EnchantmentHelper.cpp
#	Minecraft.World/Entities/HangingEntity.cpp
#	Minecraft.World/Entities/LeashFenceKnotEntity.cpp
#	Minecraft.World/Entities/LivingEntity.cpp
#	Minecraft.World/Entities/Mobs/Boat.cpp
#	Minecraft.World/Entities/Mobs/Minecart.cpp
#	Minecraft.World/Entities/Mobs/Witch.cpp
#	Minecraft.World/Entities/SyncedEntityData.cpp
#	Minecraft.World/Items/LeashItem.cpp
#	Minecraft.World/Items/PotionItem.cpp
#	Minecraft.World/Level/BaseMobSpawner.cpp
#	Minecraft.World/Level/CustomLevelSource.cpp
#	Minecraft.World/Level/Level.cpp
#	Minecraft.World/Level/Storage/DirectoryLevelStorage.cpp
#	Minecraft.World/Level/Storage/McRegionLevelStorage.cpp
#	Minecraft.World/Level/Storage/RegionFileCache.cpp
#	Minecraft.World/Player/Player.cpp
#	Minecraft.World/WorldGen/Biomes/BiomeCache.cpp
#	Minecraft.World/WorldGen/Features/RandomScatteredLargeFeature.cpp
#	Minecraft.World/WorldGen/Layers/BiomeOverrideLayer.cpp
2026-03-30 16:28:40 +11:00

225 lines
7.3 KiB
C++

#include "../../Platform/stdafx.h"
#include "../../Headers/net.minecraft.world.entity.ai.village.h"
#include "../../Headers/net.minecraft.world.level.h"
#include "../../Headers/net.minecraft.world.level.tile.h"
#include "../../Headers/net.minecraft.world.phys.h"
#include "Villages.h"
#include <limits>
const std::wstring Villages::VILLAGE_FILE_ID = L"villages";
Villages::Villages(const std::wstring& id) : SavedData(id) {
_tick = 0;
level = nullptr;
}
Villages::Villages(Level* level) : SavedData(VILLAGE_FILE_ID) {
_tick = 0;
this->level = level;
}
Villages::~Villages() {
for (auto it = queries.begin(); it != queries.end(); ++it) delete *it;
}
void Villages::setLevel(Level* level) {
this->level = level;
// for (Village village : villages)
for (auto it = villages.begin(); it != villages.end(); ++it) {
std::shared_ptr<Village> village = *it;
village->setLevel(level);
}
}
void Villages::queryUpdateAround(int x, int y, int z) {
if (queries.size() > 64) return;
if (!hasQuery(x, y, z)) queries.push_back(new Pos(x, y, z));
}
void Villages::tick() {
++_tick;
// for (Village village : villages)
for (auto it = villages.begin(); it != villages.end(); ++it) {
std::shared_ptr<Village> village = *it;
village->tick(_tick);
}
removeVillages();
processNextQuery();
cluster();
if ((_tick % 400) == 0) {
setDirty();
}
}
void Villages::removeVillages() {
// for (Iterator<Village> it = villages.iterator(); it.hasNext();)
for (auto it = villages.begin(); it != villages.end();) {
std::shared_ptr<Village> village = *it; // it.next();
if (village->canRemove()) {
it = villages.erase(it);
// it.remove();
setDirty();
} else {
++it;
}
}
}
std::vector<std::shared_ptr<Village> >* Villages::getVillages() {
return &villages;
}
std::shared_ptr<Village> Villages::getClosestVillage(int x, int y, int z,
int maxDist) {
std::shared_ptr<Village> closest = nullptr;
float closestDistSqr = std::numeric_limits<float>::max();
// for (Village village : villages)
for (auto it = villages.begin(); it != villages.end(); ++it) {
std::shared_ptr<Village> village = *it;
float distSqr = village->getCenter()->distSqr(x, y, z);
if (distSqr >= closestDistSqr) continue;
float requiredDist = maxDist + village->getRadius();
if (distSqr > requiredDist * requiredDist) continue;
closest = village;
closestDistSqr = distSqr;
}
return closest;
}
void Villages::processNextQuery() {
if (queries.empty()) return;
Pos* q = queries.front();
queries.pop_front();
addDoorInfos(q);
delete q;
}
void Villages::cluster() {
// note doesn't merge or split existing villages
// for (int i = 0; i < unclustered.size(); ++i)
for (auto it = unclustered.begin(); it != unclustered.end(); ++it) {
std::shared_ptr<DoorInfo> di = *it; // unclustered.get(i);
bool found = false;
// for (Village village : villages)
for (auto itV = villages.begin(); itV != villages.end(); ++itV) {
std::shared_ptr<Village> village = *itV;
int dist = (int)village->getCenter()->distSqr(di->x, di->y, di->z);
int radius = MaxDoorDist + village->getRadius();
if (dist > radius * radius) continue;
village->addDoorInfo(di);
found = true;
break;
}
if (found) continue;
// create new Village
std::shared_ptr<Village> village =
std::shared_ptr<Village>(new Village(level));
village->addDoorInfo(di);
villages.push_back(village);
setDirty();
}
unclustered.clear();
}
void Villages::addDoorInfos(Pos* pos) {
int scanX = 16, scanY = 4, scanZ = 16;
for (int xx = pos->x - scanX; xx < pos->x + scanX; xx++) {
for (int yy = pos->y - scanY; yy < pos->y + scanY; yy++) {
for (int zz = pos->z - scanZ; zz < pos->z + scanZ; zz++) {
if (isDoor(xx, yy, zz)) {
std::shared_ptr<DoorInfo> currentDoor =
getDoorInfo(xx, yy, zz);
if (currentDoor == nullptr)
createDoorInfo(xx, yy, zz);
else
currentDoor->timeStamp = _tick;
}
}
}
}
}
std::shared_ptr<DoorInfo> Villages::getDoorInfo(int x, int y, int z) {
// for (DoorInfo di : unclustered)
for (auto it = unclustered.begin(); it != unclustered.end(); ++it) {
std::shared_ptr<DoorInfo> di = *it;
if (di->x == x && di->z == z && abs(di->y - y) <= 1) return di;
}
// for (Village v : villages)
for (auto it = villages.begin(); it != villages.end(); ++it) {
std::shared_ptr<Village> v = *it;
std::shared_ptr<DoorInfo> di = v->getDoorInfo(x, y, z);
if (di != nullptr) return di;
}
return nullptr;
}
void Villages::createDoorInfo(int x, int y, int z) {
int dir = ((DoorTile*)Tile::door_wood)->getDir(level, x, y, z);
if (dir == 0 || dir == 2) {
int canSeeX = 0;
for (int i = -5; i < 0; ++i)
if (level->canSeeSky(x + i, y, z)) canSeeX--;
for (int i = 1; i <= 5; ++i)
if (level->canSeeSky(x + i, y, z)) canSeeX++;
if (canSeeX != 0)
unclustered.push_back(std::shared_ptr<DoorInfo>(
new DoorInfo(x, y, z, canSeeX > 0 ? -2 : 2, 0, _tick)));
} else {
int canSeeZ = 0;
for (int i = -5; i < 0; ++i)
if (level->canSeeSky(x, y, z + i)) canSeeZ--;
for (int i = 1; i <= 5; ++i)
if (level->canSeeSky(x, y, z + i)) canSeeZ++;
if (canSeeZ != 0)
unclustered.push_back(std::shared_ptr<DoorInfo>(
new DoorInfo(x, y, z, 0, canSeeZ > 0 ? -2 : 2, _tick)));
}
}
bool Villages::hasQuery(int x, int y, int z) {
// for (Pos pos : queries)
for (auto it = queries.begin(); it != queries.end(); ++it) {
Pos* pos = *it;
if (pos->x == x && pos->y == y && pos->z == z) return true;
}
return false;
}
bool Villages::isDoor(int x, int y, int z) {
int tileId = level->getTile(x, y, z);
return tileId == Tile::door_wood_Id;
}
void Villages::load(CompoundTag* tag) {
_tick = tag->getInt(L"Tick");
ListTag<CompoundTag>* villageTags =
(ListTag<CompoundTag>*)tag->getList(L"Villages");
for (int i = 0; i < villageTags->size(); i++) {
CompoundTag* compoundTag = villageTags->get(i);
std::shared_ptr<Village> village =
std::shared_ptr<Village>(new Village());
village->readAdditionalSaveData(compoundTag);
villages.push_back(village);
}
}
void Villages::save(CompoundTag* tag) {
tag->putInt(L"Tick", _tick);
ListTag<CompoundTag>* villageTags = new ListTag<CompoundTag>(L"Villages");
// for (Village village : villages)
for (auto it = villages.begin(); it != villages.end(); ++it) {
std::shared_ptr<Village> village = *it;
CompoundTag* villageTag = new CompoundTag(L"Village");
village->addAdditonalSaveData(villageTag);
villageTags->add(villageTag);
}
tag->put(L"Villages", villageTags);
}