aboutsummaryrefslogtreecommitdiff
path: root/Minecraft.World/VillageSiege.cpp
diff options
context:
space:
mode:
authordaoge_cmd <3523206925@qq.com>2026-03-01 12:16:08 +0800
committerdaoge_cmd <3523206925@qq.com>2026-03-01 12:16:08 +0800
commitb691c43c44ff180d10e7d4a9afc83b98551ff586 (patch)
tree3e9849222cbc6ba49f2f1fc6e5fe7179632c7390 /Minecraft.World/VillageSiege.cpp
parentdef8cb415354ac390b7e89052a50605285f1aca9 (diff)
Initial commit
Diffstat (limited to 'Minecraft.World/VillageSiege.cpp')
-rw-r--r--Minecraft.World/VillageSiege.cpp169
1 files changed, 169 insertions, 0 deletions
diff --git a/Minecraft.World/VillageSiege.cpp b/Minecraft.World/VillageSiege.cpp
new file mode 100644
index 00000000..55b2a3e8
--- /dev/null
+++ b/Minecraft.World/VillageSiege.cpp
@@ -0,0 +1,169 @@
+#include "stdafx.h"
+#include "net.minecraft.world.entity.ai.village.h"
+#include "net.minecraft.world.entity.h"
+#include "net.minecraft.world.entity.monster.h"
+#include "net.minecraft.world.level.h"
+#include "VillageSiege.h"
+
+VillageSiege::VillageSiege(Level *level)
+{
+ hasSetupSiege = false;
+ siegeState = SIEGE_NOT_INITED;
+ siegeCount = 0;
+ nextSpawnTime = 0;
+ village = weak_ptr<Village>();
+ spawnX = spawnY = spawnZ = 0;
+
+ this->level = level;
+}
+
+void VillageSiege::tick()
+{
+ bool debug = false;
+ if (debug)
+ {
+ if (siegeState == SIEGE_DONE)
+ {
+ siegeCount = 100;
+ return;
+ }
+ // return;
+ }
+ else
+ {
+ if (level->isDay())
+ {
+ siegeState = SIEGE_CAN_ACTIVATE;
+ return;
+ }
+
+ if (siegeState == SIEGE_DONE) return;
+
+ if (siegeState == SIEGE_CAN_ACTIVATE)
+ {
+ float timeOfDay = level->getTimeOfDay(0);
+ if (timeOfDay < 0.50 || timeOfDay > 0.501) return;
+ siegeState = level->random->nextInt(10) == 0 ? SIEGE_TONIGHT : SIEGE_DONE;
+ hasSetupSiege = false;
+ if (siegeState == SIEGE_DONE) return;
+ }
+ }
+
+ if (!hasSetupSiege)
+ {
+ if (tryToSetupSiege()) hasSetupSiege = true;
+ else return;
+ }
+
+ // Siege!
+ if (nextSpawnTime > 0)
+ {
+ --nextSpawnTime;
+ return;
+ }
+
+ nextSpawnTime = 2; // 50 + level.random.nextInt(100);
+ if (siegeCount > 0)
+ {
+ trySpawn();
+ --siegeCount;
+ }
+ else
+ {
+ siegeState = SIEGE_DONE;
+ }
+
+}
+
+bool VillageSiege::tryToSetupSiege()
+{
+ vector<shared_ptr<Player> > *players = &level->players;
+ //for (Player player : players)
+ for(AUTO_VAR(it, players->begin()); it != players->end(); ++it)
+ {
+ shared_ptr<Player> player = *it;
+ shared_ptr<Village> _village = level->villages->getClosestVillage((int) player->x, (int) player->y, (int) player->z, 1);
+ village = _village;
+
+ if (_village == NULL) continue;
+ if (_village->getDoorCount() < 10) continue;
+ if (_village->getStableAge() < 20) continue;
+ if (_village->getPopulationSize() < 20) continue;
+
+ // setup siege origin
+ Pos *center = _village->getCenter();
+ float radius = _village->getRadius();
+
+ bool overlaps = false;
+ for (int i = 0; i < 10; ++i)
+ {
+ spawnX = center->x + (int) (Mth::cos(level->random->nextFloat() * PI * 2.f) * radius * 0.9);
+ spawnY = center->y;
+ spawnZ = center->z + (int) (Mth::sin(level->random->nextFloat() * PI * 2.f) * radius * 0.9);
+ overlaps = false;
+ vector<shared_ptr<Village> > *villages = level->villages->getVillages();
+ //for (Village v : level.villages.getVillages())
+ for(AUTO_VAR(itV, villages->begin()); itV != villages->end(); ++itV)
+ {
+ shared_ptr<Village>v = *itV;
+ if (v == _village) continue;
+ if (v->isInside(spawnX, spawnY, spawnZ))
+ {
+ overlaps = true;
+ break;
+ }
+ }
+ if (!overlaps) break;
+ }
+ if (overlaps) return false;
+
+ Vec3 *spawnPos = findRandomSpawnPos(spawnX, spawnY, spawnZ);
+ if (spawnPos == NULL) continue;
+
+ nextSpawnTime = 0;
+ siegeCount = 20;
+ return true;
+ }
+ return false;
+}
+
+bool VillageSiege::trySpawn()
+{
+ Vec3 *spawnPos = findRandomSpawnPos(spawnX, spawnY, spawnZ);
+ if (spawnPos == NULL) return false;
+ shared_ptr<Zombie> mob;
+ //try
+ {
+ mob = shared_ptr<Zombie>( new Zombie(level) );
+ mob->finalizeMobSpawn();
+ mob->setVillager(false);
+ }
+ //catch (Exception e) {
+ // e.printStackTrace();
+ // return false;
+ //}
+ mob->moveTo(spawnPos->x, spawnPos->y, spawnPos->z, level->random->nextFloat() * 360, 0);
+ level->addEntity(mob);
+ shared_ptr<Village> _village = village.lock();
+ if( _village == NULL ) return false;
+
+ Pos *center = _village->getCenter();
+ mob->restrictTo(center->x, center->y, center->z, _village->getRadius());
+ return true;
+}
+
+Vec3 *VillageSiege::findRandomSpawnPos(int x, int y, int z)
+{
+ shared_ptr<Village> _village = village.lock();
+ if( _village == NULL ) return NULL;
+
+ for (int i = 0; i < 10; ++i)
+ {
+ int xx = x + level->random->nextInt(16) - 8;
+ int yy = y + level->random->nextInt(6) - 3;
+ int zz = z + level->random->nextInt(16) - 8;
+ if (!_village->isInside(xx, yy, zz)) continue;
+ if (MobSpawner::isSpawnPositionOk(MobCategory::monster, level, xx, yy, zz)) return Vec3::newTemp(xx, yy, zz);
+ }
+ return NULL;
+} \ No newline at end of file