the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
1#include "stdafx.h"
2#include "net.minecraft.world.entity.ai.village.h"
3#include "net.minecraft.world.entity.npc.h"
4#include "net.minecraft.world.entity.animal.h"
5#include "net.minecraft.world.level.h"
6#include "net.minecraft.world.level.tile.h"
7#include "net.minecraft.world.phys.h"
8#include "BasicTypeContainers.h"
9#include "Village.h"
10
11Village::Aggressor::Aggressor(shared_ptr<LivingEntity> mob, int timeStamp)
12{
13 this->mob = mob;
14 this->timeStamp = timeStamp;
15}
16
17Village::Village()
18{
19 accCenter = new Pos(0, 0, 0);
20 center = new Pos(0, 0, 0);
21 radius = 0;
22 stableSince = 0;
23 _tick = 0;
24 populationSize = 0;
25 golemCount = 0;
26 noBreedTimer = 0;
27
28 level = NULL;
29}
30
31Village::Village(Level *level)
32{
33 accCenter = new Pos(0, 0, 0);
34 center = new Pos(0, 0, 0);
35 radius = 0;
36 stableSince = 0;
37 _tick = 0;
38 populationSize = 0;
39 golemCount = 0;
40 noBreedTimer = 0;
41
42 this->level = level;
43}
44
45Village::~Village()
46{
47 delete accCenter;
48 delete center;
49 for(AUTO_VAR(it, aggressors.begin()); it != aggressors.end(); ++it)
50 {
51 delete *it;
52 }
53}
54
55void Village::setLevel(Level *level)
56{
57 this->level = level;
58}
59
60void Village::tick(int tick)
61{
62 this->_tick = tick;
63 updateDoors();
64 updateAggressors();
65 if (tick % 20 == 0) countPopulation();
66 if (tick % 30 == 0) countGolem();
67
68 int idealGolemCount = populationSize / 10;
69 if (golemCount < idealGolemCount && doorInfos.size() > 20 && level->random->nextInt(7000) == 0)
70 {
71 Vec3 *spawnPos = findRandomSpawnPos(center->x, center->y, center->z, 2, 4, 2);
72 if (spawnPos != NULL)
73 {
74 shared_ptr<VillagerGolem> vg = shared_ptr<VillagerGolem>( new VillagerGolem(level) );
75 vg->setPos(spawnPos->x, spawnPos->y, spawnPos->z);
76 level->addEntity(vg);
77 ++golemCount;
78 }
79 }
80
81 // 4J - All commented out in java
82 // for (DoorInfo di : doorInfos) {
83 // level.addParticle("heart", di.getIndoorX() + 0.5, di.getIndoorY() + .5f, di.getIndoorZ() + 0.5, 0, 1, 0);
84 // }
85 //
86 // for (int i = 0; i < 8; ++i)
87 // for (int j = 0; j < 8; ++j)
88 // level.addParticle("heart", center.x + 0.5 + i, center.y + .5f, center.z + 0.5 + j, 0, 1, 0);
89 // for (float i = 0; i < Math.PI * 2; i += 0.1) {
90 // int x = center.x + (int) (Math.cos(i) * radius);
91 // int z = center.z + (int) (Math.sin(i) * radius);
92 // level.addParticle("heart", x, center.y + .5f, z, 0, 1, 0);
93 // }
94}
95
96Vec3 *Village::findRandomSpawnPos(int x, int y, int z, int sx, int sy, int sz)
97{
98 for (int i = 0; i < 10; ++i)
99 {
100 int xx = x + level->random->nextInt(16) - 8;
101 int yy = y + level->random->nextInt(6) - 3;
102 int zz = z + level->random->nextInt(16) - 8;
103 if (!isInside(xx, yy, zz)) continue;
104 if (canSpawnAt(xx, yy, zz, sx, sy, sz)) return Vec3::newTemp(xx, yy, zz);
105 }
106 return NULL;
107}
108
109bool Village::canSpawnAt(int x, int y, int z, int sx, int sy, int sz)
110{
111 if (!level->isTopSolidBlocking(x, y - 1, z)) return false;
112
113 int startX = x - sx / 2;
114 int startZ = z - sz / 2;
115 for (int xx = startX; xx < startX + sx; xx++)
116 for (int yy = y; yy < y + sy; yy++)
117 for (int zz = startZ; zz < startZ + sz; zz++)
118 if (level->isSolidBlockingTile(xx, yy, zz)) return false;
119
120 return true;
121}
122
123void Village::countGolem()
124{
125 // Fix - let bots report themselves?
126 vector<shared_ptr<Entity> > *golems = level->getEntitiesOfClass(typeid(VillagerGolem), AABB::newTemp(center->x - radius, center->y - 4, center->z - radius, center->x + radius, center->y + 4, center->z + radius));
127 golemCount = golems->size();
128 delete golems;
129}
130
131void Village::countPopulation()
132{
133 vector<shared_ptr<Entity> > *villagers = level->getEntitiesOfClass(typeid(Villager), AABB::newTemp(center->x - radius, center->y - 4, center->z - radius, center->x + radius, center->y + 4, center->z + radius));
134 populationSize = villagers->size();
135 delete villagers;
136
137 if (populationSize == 0)
138 {
139 // forget standing
140 playerStanding.clear();
141 }
142}
143
144Pos *Village::getCenter()
145{
146 return center;
147}
148
149int Village::getRadius()
150{
151 return radius;
152}
153
154int Village::getDoorCount()
155{
156 return doorInfos.size();
157}
158
159int Village::getStableAge()
160{
161 return _tick - stableSince;
162}
163
164int Village::getPopulationSize()
165{
166 return populationSize;
167}
168
169bool Village::isInside(int xx, int yy, int zz)
170{
171 return center->distSqr(xx, yy, zz) < radius * radius;
172}
173
174vector<shared_ptr<DoorInfo> > *Village::getDoorInfos()
175{
176 return &doorInfos;
177}
178
179shared_ptr<DoorInfo> Village::getClosestDoorInfo(int x, int y, int z)
180{
181 shared_ptr<DoorInfo> closest = nullptr;
182 int closestDistSqr = Integer::MAX_VALUE;
183 //for (DoorInfo dm : doorInfos)
184 for(AUTO_VAR(it, doorInfos.begin()); it != doorInfos.end(); ++it)
185 {
186 shared_ptr<DoorInfo> dm = *it;
187 int distSqr = dm->distanceToSqr(x, y, z);
188 if (distSqr < closestDistSqr)
189 {
190 closest = dm;
191 closestDistSqr = distSqr;
192 }
193 }
194 return closest;
195}
196
197shared_ptr<DoorInfo>Village::getBestDoorInfo(int x, int y, int z)
198{
199 shared_ptr<DoorInfo> closest = nullptr;
200 int closestDist = Integer::MAX_VALUE;
201 //for (DoorInfo dm : doorInfos)
202 for(AUTO_VAR(it, doorInfos.begin()); it != doorInfos.end(); ++it)
203 {
204 shared_ptr<DoorInfo>dm = *it;
205
206 int distSqr = dm->distanceToSqr(x, y, z);
207 if (distSqr > 16 * 16) distSqr *= 1000;
208 else distSqr = dm->getBookingsCount();
209
210 if (distSqr < closestDist)
211 {
212 closest = dm;
213 closestDist = distSqr;
214 }
215 }
216 return closest;
217}
218
219bool Village::hasDoorInfo(int x, int y, int z)
220{
221 return getDoorInfo(x, y, z) != NULL;
222}
223
224shared_ptr<DoorInfo>Village::getDoorInfo(int x, int y, int z)
225{
226 if (center->distSqr(x, y, z) > radius * radius) return nullptr;
227 //for (DoorInfo di : doorInfos)
228 for(AUTO_VAR(it, doorInfos.begin()); it != doorInfos.end(); ++it)
229 {
230 shared_ptr<DoorInfo> di = *it;
231 if (di->x == x && di->z == z && abs(di->y - y) <= 1) return di;
232 }
233 return nullptr;
234}
235
236void Village::addDoorInfo(shared_ptr<DoorInfo> di)
237{
238 doorInfos.push_back(di);
239 accCenter->x += di->x;
240 accCenter->y += di->y;
241 accCenter->z += di->z;
242 calcInfo();
243 stableSince = di->timeStamp;
244}
245
246bool Village::canRemove()
247{
248 return doorInfos.empty();
249}
250
251void Village::addAggressor(shared_ptr<LivingEntity> mob)
252{
253 //for (Aggressor a : aggressors)
254 for(AUTO_VAR(it, aggressors.begin()); it != aggressors.end(); ++it)
255 {
256 Aggressor *a = *it;
257 if (a->mob == mob)
258 {
259 a->timeStamp = _tick;
260 return;
261 }
262 }
263 aggressors.push_back(new Aggressor(mob, _tick));
264}
265
266shared_ptr<LivingEntity> Village::getClosestAggressor(shared_ptr<LivingEntity> from)
267{
268 double closestSqr = Double::MAX_VALUE;
269 Aggressor *closest = NULL;
270 //for (int i = 0; i < aggressors.size(); ++i)
271 for(AUTO_VAR(it, aggressors.begin()); it != aggressors.end(); ++it)
272 {
273 Aggressor *a = *it; //aggressors.get(i);
274 double distSqr = a->mob->distanceToSqr(from);
275 if (distSqr > closestSqr) continue;
276 closest = a;
277 closestSqr = distSqr;
278 }
279 return closest != NULL ? closest->mob : nullptr;
280}
281
282shared_ptr<Player> Village::getClosestBadStandingPlayer(shared_ptr<LivingEntity> from)
283{
284 double closestSqr = Double::MAX_VALUE;
285 shared_ptr<Player> closest = nullptr;
286
287 //for (String player : playerStanding.keySet())
288 for(AUTO_VAR(it,playerStanding.begin()); it != playerStanding.end(); ++it)
289 {
290 wstring player = it->first;
291 if (isVeryBadStanding(player))
292 {
293 shared_ptr<Player> mob = level->getPlayerByName(player);
294 if (mob != NULL)
295 {
296 double distSqr = mob->distanceToSqr(from);
297 if (distSqr > closestSqr) continue;
298 closest = mob;
299 closestSqr = distSqr;
300 }
301 }
302 }
303
304 return closest;
305}
306
307void Village::updateAggressors()
308{
309 //for (Iterator<Aggressor> it = aggressors.iterator(); it.hasNext();)
310 for(AUTO_VAR(it, aggressors.begin()); it != aggressors.end();)
311 {
312 Aggressor *a = *it; //it.next();
313 if (!a->mob->isAlive() || abs(_tick - a->timeStamp) > 300)
314 {
315 delete *it;
316 it = aggressors.erase(it);
317 //it.remove();
318 }
319 else
320 {
321 ++it;
322 }
323 }
324}
325
326void Village::updateDoors()
327{
328 bool removed = false;
329 bool resetBookings = level->random->nextInt(50) == 0;
330 //for (Iterator<DoorInfo> it = doorInfos.iterator(); it.hasNext();)
331 for(AUTO_VAR(it, doorInfos.begin()); it != doorInfos.end();)
332 {
333 shared_ptr<DoorInfo> dm = *it; //it.next();
334 if (resetBookings) dm->resetBookingCount();
335 if (!isDoor(dm->x, dm->y, dm->z) || abs(_tick - dm->timeStamp) > 1200)
336 {
337 accCenter->x -= dm->x;
338 accCenter->y -= dm->y;
339 accCenter->z -= dm->z;
340 removed = true;
341 dm->removed = true;
342
343 it = doorInfos.erase(it);
344 //it.remove();
345 }
346 else
347 {
348 ++it;
349 }
350 }
351
352 if (removed) calcInfo();
353}
354
355bool Village::isDoor(int x, int y, int z)
356{
357 int tileId = level->getTile(x, y, z);
358 if (tileId <= 0) return false;
359 return tileId == Tile::door_wood_Id;
360}
361
362void Village::calcInfo()
363{
364 int s = doorInfos.size();
365 if (s == 0)
366 {
367 center->set(0, 0, 0);
368 radius = 0;
369 return;
370 }
371 center->set(accCenter->x / s, accCenter->y / s, accCenter->z / s);
372 int maxRadiusSqr = 0;
373 //for (DoorInfo dm : doorInfos)
374 for(AUTO_VAR(it, doorInfos.begin()); it != doorInfos.end(); ++it)
375 {
376 shared_ptr<DoorInfo> dm = *it;
377 maxRadiusSqr = max(dm->distanceToSqr(center->x, center->y, center->z), maxRadiusSqr);
378 }
379 int doorDist= Villages::MaxDoorDist; // Take into local int for PS4 as max takes a reference to the const int there and then needs the value to exist for the linker
380 radius = max(doorDist, (int) sqrt((float)maxRadiusSqr) + 1);
381}
382
383int Village::getStanding(const wstring &playerName)
384{
385 AUTO_VAR(it,playerStanding.find(playerName));
386 if (it != playerStanding.end())
387 {
388 return it->second;
389 }
390 return 0;
391}
392
393int Village::modifyStanding(const wstring &playerName, int delta)
394{
395 int current = getStanding(playerName);
396 int newValue = Mth::clamp(current + delta, -30, 10);
397 playerStanding.insert(pair<wstring,int>(playerName, newValue));
398 return newValue;
399}
400
401bool Village::isGoodStanding(const wstring &playerName)
402{
403 return getStanding(playerName) >= 0;
404}
405
406bool Village::isBadStanding(const wstring &playerName)
407{
408 return getStanding(playerName) <= -5;
409}
410
411bool Village::isVeryBadStanding(const wstring playerName)
412{
413 return getStanding(playerName) <= -15;
414}
415
416void Village::readAdditionalSaveData(CompoundTag *tag)
417{
418 populationSize = tag->getInt(L"PopSize");
419 radius = tag->getInt(L"Radius");
420 golemCount = tag->getInt(L"Golems");
421 stableSince = tag->getInt(L"Stable");
422 _tick = tag->getInt(L"Tick");
423 noBreedTimer = tag->getInt(L"MTick");
424 center->x = tag->getInt(L"CX");
425 center->y = tag->getInt(L"CY");
426 center->z = tag->getInt(L"CZ");
427 accCenter->x = tag->getInt(L"ACX");
428 accCenter->y = tag->getInt(L"ACY");
429 accCenter->z = tag->getInt(L"ACZ");
430
431 ListTag<CompoundTag> *doorTags = (ListTag<CompoundTag> *) tag->getList(L"Doors");
432 for (int i = 0; i < doorTags->size(); i++)
433 {
434 CompoundTag *dTag = doorTags->get(i);
435
436 shared_ptr<DoorInfo> door = shared_ptr<DoorInfo>(new DoorInfo(dTag->getInt(L"X"), dTag->getInt(L"Y"), dTag->getInt(L"Z"), dTag->getInt(L"IDX"), dTag->getInt(L"IDZ"), dTag->getInt(L"TS")));
437 doorInfos.push_back(door);
438 }
439
440 ListTag<CompoundTag> *playerTags = (ListTag<CompoundTag> *) tag->getList(L"Players");
441 for (int i = 0; i < playerTags->size(); i++)
442 {
443 CompoundTag *pTag = playerTags->get(i);
444 playerStanding.insert(pair<wstring,int>(pTag->getString(L"Name"), pTag->getInt(L"S")));
445 }
446}
447
448void Village::addAdditonalSaveData(CompoundTag *tag)
449{
450 tag->putInt(L"PopSize", populationSize);
451 tag->putInt(L"Radius", radius);
452 tag->putInt(L"Golems", golemCount);
453 tag->putInt(L"Stable", stableSince);
454 tag->putInt(L"Tick", _tick);
455 tag->putInt(L"MTick", noBreedTimer);
456 tag->putInt(L"CX", center->x);
457 tag->putInt(L"CY", center->y);
458 tag->putInt(L"CZ", center->z);
459 tag->putInt(L"ACX", accCenter->x);
460 tag->putInt(L"ACY", accCenter->y);
461 tag->putInt(L"ACZ", accCenter->z);
462
463 ListTag<CompoundTag> *doorTags = new ListTag<CompoundTag>(L"Doors");
464 //for (DoorInfo dm : doorInfos)
465 for(AUTO_VAR(it,doorInfos.begin()); it != doorInfos.end(); ++it)
466 {
467 shared_ptr<DoorInfo> dm = *it;
468 CompoundTag *doorTag = new CompoundTag(L"Door");
469 doorTag->putInt(L"X", dm->x);
470 doorTag->putInt(L"Y", dm->y);
471 doorTag->putInt(L"Z", dm->z);
472 doorTag->putInt(L"IDX", dm->insideDx);
473 doorTag->putInt(L"IDZ", dm->insideDz);
474 doorTag->putInt(L"TS", dm->timeStamp);
475 doorTags->add(doorTag);
476 }
477 tag->put(L"Doors", doorTags);
478
479 ListTag<CompoundTag> *playerTags = new ListTag<CompoundTag>(L"Players");
480 //for (String player : playerStanding.keySet())
481 for(AUTO_VAR(it, playerStanding.begin()); it != playerStanding.end(); ++it)
482 {
483 wstring player = it->first;
484 CompoundTag *playerTag = new CompoundTag(player);
485 playerTag->putString(L"Name", player);
486 playerTag->putInt(L"S", it->second);
487 playerTags->add(playerTag);
488 }
489 tag->put(L"Players", playerTags);
490
491}
492
493void Village::resetNoBreedTimer()
494{
495 noBreedTimer = _tick;
496}
497
498bool Village::isBreedTimerOk()
499{
500 // prevent new villagers if a villager was killed by a mob within 3
501 // minutes
502 return noBreedTimer == 0 || (_tick - noBreedTimer) >= (SharedConstants::TICKS_PER_SECOND * 60 * 3);
503}
504
505void Village::rewardAllPlayers(int amount)
506{
507 //for (String player : playerStanding.keySet())
508 for(AUTO_VAR(it, playerStanding.begin()); it != playerStanding.end(); ++it)
509 {
510 modifyStanding(it->first, amount);
511 }
512}